2017-07-14 10:28:59 +02:00
|
|
|
|
/*
|
2020-01-06 15:24:46 +01:00
|
|
|
|
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
|
2017-07-14 10:28:59 +02:00
|
|
|
|
*
|
|
|
|
|
* 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/.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-03-15 15:55:34 +01:00
|
|
|
|
using System;
|
2019-05-08 13:53:38 +02:00
|
|
|
|
using System.Net.Http;
|
2019-09-12 12:31:17 +02:00
|
|
|
|
using System.Threading.Tasks;
|
2020-05-15 16:13:15 +02:00
|
|
|
|
using CefSharp;
|
2019-08-30 09:55:26 +02:00
|
|
|
|
using SafeExamBrowser.Applications.Contracts;
|
|
|
|
|
using SafeExamBrowser.Applications.Contracts.Events;
|
2019-12-03 15:43:48 +01:00
|
|
|
|
using SafeExamBrowser.Applications.Contracts.Resources.Icons;
|
2019-09-06 08:13:27 +02:00
|
|
|
|
using SafeExamBrowser.Browser.Contracts.Events;
|
2019-09-24 08:53:29 +02:00
|
|
|
|
using SafeExamBrowser.Browser.Contracts.Filters;
|
2019-01-17 11:12:17 +01:00
|
|
|
|
using SafeExamBrowser.Browser.Events;
|
2019-09-13 09:17:14 +02:00
|
|
|
|
using SafeExamBrowser.Browser.Filters;
|
2018-03-08 07:35:58 +01:00
|
|
|
|
using SafeExamBrowser.Browser.Handlers;
|
2019-08-30 09:55:26 +02:00
|
|
|
|
using SafeExamBrowser.Configuration.Contracts;
|
|
|
|
|
using SafeExamBrowser.I18n.Contracts;
|
|
|
|
|
using SafeExamBrowser.Logging.Contracts;
|
2019-09-10 11:01:49 +02:00
|
|
|
|
using SafeExamBrowser.Settings.Browser;
|
2019-12-18 08:24:55 +01:00
|
|
|
|
using SafeExamBrowser.Settings.Browser.Filter;
|
2019-08-30 09:55:26 +02:00
|
|
|
|
using SafeExamBrowser.UserInterface.Contracts;
|
|
|
|
|
using SafeExamBrowser.UserInterface.Contracts.Browser;
|
2020-01-22 15:16:11 +01:00
|
|
|
|
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
|
|
|
|
|
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
|
2019-08-30 09:55:26 +02:00
|
|
|
|
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
|
2020-08-05 22:55:38 +02:00
|
|
|
|
using Syroot.Windows.IO;
|
2020-05-15 16:13:15 +02:00
|
|
|
|
using BrowserSettings = SafeExamBrowser.Settings.Browser.BrowserSettings;
|
|
|
|
|
using Request = SafeExamBrowser.Browser.Contracts.Filters.Request;
|
2020-08-03 14:41:25 +02:00
|
|
|
|
using ResourceHandler = SafeExamBrowser.Browser.Handlers.ResourceHandler;
|
2020-05-15 16:13:15 +02:00
|
|
|
|
using TitleChangedEventHandler = SafeExamBrowser.Applications.Contracts.Events.TitleChangedEventHandler;
|
2017-07-14 10:28:59 +02:00
|
|
|
|
|
|
|
|
|
namespace SafeExamBrowser.Browser
|
|
|
|
|
{
|
2019-11-28 17:22:04 +01:00
|
|
|
|
internal class BrowserApplicationInstance : IApplicationWindow
|
2017-07-14 10:28:59 +02:00
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
private const double ZOOM_FACTOR = 0.2;
|
|
|
|
|
|
2018-06-29 09:50:20 +02:00
|
|
|
|
private AppConfig appConfig;
|
2017-07-31 20:22:53 +02:00
|
|
|
|
private IBrowserControl control;
|
|
|
|
|
private IBrowserWindow window;
|
2019-05-08 13:53:38 +02:00
|
|
|
|
private HttpClient httpClient;
|
2018-03-14 11:13:30 +01:00
|
|
|
|
private bool isMainInstance;
|
2020-01-22 15:16:11 +01:00
|
|
|
|
private IFileSystemDialog fileSystemDialog;
|
2019-01-17 11:12:17 +01:00
|
|
|
|
private IMessageBox messageBox;
|
2018-08-31 15:29:36 +02:00
|
|
|
|
private IModuleLogger logger;
|
2018-03-14 11:13:30 +01:00
|
|
|
|
private BrowserSettings settings;
|
2019-12-19 15:02:40 +01:00
|
|
|
|
private string startUrl;
|
2018-03-14 11:13:30 +01:00
|
|
|
|
private IText text;
|
|
|
|
|
private IUserInterfaceFactory uiFactory;
|
2019-05-22 11:42:31 +02:00
|
|
|
|
private double zoomLevel;
|
2019-01-23 09:37:47 +01:00
|
|
|
|
|
2019-12-18 08:24:55 +01:00
|
|
|
|
private WindowSettings WindowSettings
|
2019-01-23 09:37:47 +01:00
|
|
|
|
{
|
2019-09-10 11:53:30 +02:00
|
|
|
|
get { return isMainInstance ? settings.MainWindow : settings.AdditionalWindow; }
|
2019-01-23 09:37:47 +01:00
|
|
|
|
}
|
2017-07-31 20:22:53 +02:00
|
|
|
|
|
2019-11-29 14:59:54 +01:00
|
|
|
|
internal int Id { get; }
|
2019-11-28 17:22:04 +01:00
|
|
|
|
|
2019-12-05 11:54:43 +01:00
|
|
|
|
public IntPtr Handle { get; private set; }
|
2019-11-15 16:00:03 +01:00
|
|
|
|
public IconResource Icon { get; private set; }
|
2019-11-28 17:22:04 +01:00
|
|
|
|
public string Title { get; private set; }
|
|
|
|
|
|
|
|
|
|
internal event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
|
|
|
|
internal event PopupRequestedEventHandler PopupRequested;
|
2020-09-21 19:22:15 +02:00
|
|
|
|
internal event ResetRequestedEventHandler ResetRequested;
|
2020-08-03 14:41:25 +02:00
|
|
|
|
internal event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
|
2019-11-28 17:22:04 +01:00
|
|
|
|
internal event InstanceTerminatedEventHandler Terminated;
|
2019-12-19 15:02:40 +01:00
|
|
|
|
internal event TerminationRequestedEventHandler TerminationRequested;
|
2017-07-14 10:28:59 +02:00
|
|
|
|
|
2019-01-17 16:15:10 +01:00
|
|
|
|
public event IconChangedEventHandler IconChanged;
|
2019-11-28 17:22:04 +01:00
|
|
|
|
public event TitleChangedEventHandler TitleChanged;
|
2017-07-28 09:12:17 +02:00
|
|
|
|
|
2018-06-21 07:56:25 +02:00
|
|
|
|
public BrowserApplicationInstance(
|
2018-06-29 09:50:20 +02:00
|
|
|
|
AppConfig appConfig,
|
2018-06-21 07:56:25 +02:00
|
|
|
|
BrowserSettings settings,
|
2019-11-29 14:59:54 +01:00
|
|
|
|
int id,
|
2018-08-31 07:49:41 +02:00
|
|
|
|
bool isMainInstance,
|
2020-01-22 15:16:11 +01:00
|
|
|
|
IFileSystemDialog fileSystemDialog,
|
2019-01-17 11:12:17 +01:00
|
|
|
|
IMessageBox messageBox,
|
2018-08-31 15:29:36 +02:00
|
|
|
|
IModuleLogger logger,
|
2018-06-21 07:56:25 +02:00
|
|
|
|
IText text,
|
2019-01-23 09:37:47 +01:00
|
|
|
|
IUserInterfaceFactory uiFactory,
|
2019-12-19 15:02:40 +01:00
|
|
|
|
string startUrl)
|
2018-03-14 11:13:30 +01:00
|
|
|
|
{
|
2018-06-29 09:50:20 +02:00
|
|
|
|
this.appConfig = appConfig;
|
2018-08-31 07:49:41 +02:00
|
|
|
|
this.Id = id;
|
2019-05-08 13:53:38 +02:00
|
|
|
|
this.httpClient = new HttpClient();
|
2018-03-14 11:13:30 +01:00
|
|
|
|
this.isMainInstance = isMainInstance;
|
2020-01-22 15:16:11 +01:00
|
|
|
|
this.fileSystemDialog = fileSystemDialog;
|
2019-01-17 11:12:17 +01:00
|
|
|
|
this.messageBox = messageBox;
|
2018-08-31 15:29:36 +02:00
|
|
|
|
this.logger = logger;
|
2018-03-14 11:13:30 +01:00
|
|
|
|
this.settings = settings;
|
|
|
|
|
this.text = text;
|
|
|
|
|
this.uiFactory = uiFactory;
|
2019-12-19 15:02:40 +01:00
|
|
|
|
this.startUrl = startUrl;
|
2018-03-14 11:13:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-30 12:30:00 +02:00
|
|
|
|
public void Activate()
|
|
|
|
|
{
|
2019-11-28 17:22:04 +01:00
|
|
|
|
window.BringToForeground();
|
2019-08-30 12:30:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-28 17:22:04 +01:00
|
|
|
|
internal void Initialize()
|
2019-09-06 08:13:27 +02:00
|
|
|
|
{
|
|
|
|
|
InitializeControl();
|
|
|
|
|
InitializeWindow();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-28 17:22:04 +01:00
|
|
|
|
internal void Terminate()
|
2019-09-06 08:13:27 +02:00
|
|
|
|
{
|
2019-11-28 17:22:04 +01:00
|
|
|
|
window.Close();
|
2020-09-21 19:22:15 +02:00
|
|
|
|
control.Destroy();
|
2019-09-06 08:13:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializeControl()
|
2017-07-14 10:28:59 +02:00
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
var contextMenuHandler = new ContextMenuHandler();
|
2020-01-20 16:13:08 +01:00
|
|
|
|
var dialogHandler = new DialogHandler();
|
2019-01-17 16:15:10 +01:00
|
|
|
|
var displayHandler = new DisplayHandler();
|
2019-12-19 15:02:40 +01:00
|
|
|
|
var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} #{Id}");
|
2018-08-31 15:29:36 +02:00
|
|
|
|
var downloadHandler = new DownloadHandler(appConfig, settings, downloadLogger);
|
2019-01-17 11:12:17 +01:00
|
|
|
|
var keyboardHandler = new KeyboardHandler();
|
|
|
|
|
var lifeSpanHandler = new LifeSpanHandler();
|
2019-09-13 09:17:14 +02:00
|
|
|
|
var requestFilter = new RequestFilter();
|
2019-12-19 15:02:40 +01:00
|
|
|
|
var requestLogger = logger.CloneFor($"{nameof(RequestHandler)} #{Id}");
|
2020-08-03 14:41:25 +02:00
|
|
|
|
var resourceHandler = new ResourceHandler(appConfig, settings, requestFilter, logger, text);
|
|
|
|
|
var requestHandler = new RequestHandler(appConfig, requestFilter, requestLogger, settings, resourceHandler, text);
|
2018-06-21 07:56:25 +02:00
|
|
|
|
|
2019-11-15 16:00:03 +01:00
|
|
|
|
Icon = new BrowserIconResource();
|
|
|
|
|
|
2020-01-20 16:13:08 +01:00
|
|
|
|
dialogHandler.DialogRequested += DialogHandler_DialogRequested;
|
2019-01-17 16:15:10 +01:00
|
|
|
|
displayHandler.FaviconChanged += DisplayHandler_FaviconChanged;
|
2019-05-22 11:42:31 +02:00
|
|
|
|
displayHandler.ProgressChanged += DisplayHandler_ProgressChanged;
|
2018-10-30 11:24:28 +01:00
|
|
|
|
downloadHandler.ConfigurationDownloadRequested += DownloadHandler_ConfigurationDownloadRequested;
|
2020-01-22 15:16:11 +01:00
|
|
|
|
downloadHandler.DownloadUpdated += DownloadHandler_DownloadUpdated;
|
2020-08-10 21:42:51 +02:00
|
|
|
|
keyboardHandler.FindRequested += KeyboardHandler_FindRequested;
|
2019-01-18 16:11:33 +01:00
|
|
|
|
keyboardHandler.ReloadRequested += ReloadRequested;
|
|
|
|
|
keyboardHandler.ZoomInRequested += ZoomInRequested;
|
|
|
|
|
keyboardHandler.ZoomOutRequested += ZoomOutRequested;
|
|
|
|
|
keyboardHandler.ZoomResetRequested += ZoomResetRequested;
|
2019-01-17 11:12:17 +01:00
|
|
|
|
lifeSpanHandler.PopupRequested += LifeSpanHandler_PopupRequested;
|
2020-08-03 14:41:25 +02:00
|
|
|
|
resourceHandler.SessionIdentifierDetected += (id) => SessionIdentifierDetected?.Invoke(id);
|
2019-12-19 15:02:40 +01:00
|
|
|
|
requestHandler.QuitUrlVisited += RequestHandler_QuitUrlVisited;
|
2019-09-12 12:31:17 +02:00
|
|
|
|
requestHandler.RequestBlocked += RequestHandler_RequestBlocked;
|
2017-07-31 20:22:53 +02:00
|
|
|
|
|
2019-09-24 08:53:29 +02:00
|
|
|
|
InitializeRequestFilter(requestFilter);
|
|
|
|
|
|
2020-03-18 10:24:22 +01:00
|
|
|
|
control = new BrowserControl(
|
|
|
|
|
contextMenuHandler,
|
|
|
|
|
dialogHandler,
|
|
|
|
|
displayHandler,
|
|
|
|
|
downloadHandler,
|
|
|
|
|
keyboardHandler,
|
|
|
|
|
lifeSpanHandler,
|
|
|
|
|
requestHandler,
|
|
|
|
|
startUrl);
|
2019-09-24 08:53:29 +02:00
|
|
|
|
control.AddressChanged += Control_AddressChanged;
|
2020-05-15 16:13:15 +02:00
|
|
|
|
control.LoadFailed += Control_LoadFailed;
|
2019-09-24 08:53:29 +02:00
|
|
|
|
control.LoadingStateChanged += Control_LoadingStateChanged;
|
|
|
|
|
control.TitleChanged += Control_TitleChanged;
|
|
|
|
|
|
|
|
|
|
control.Initialize();
|
|
|
|
|
logger.Debug("Initialized browser control.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializeRequestFilter(IRequestFilter requestFilter)
|
|
|
|
|
{
|
2019-09-13 09:17:14 +02:00
|
|
|
|
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).");
|
|
|
|
|
|
2019-09-24 08:53:29 +02:00
|
|
|
|
if (requestFilter.Process(new Request { Url = settings.StartUrl }) != FilterResult.Allow)
|
|
|
|
|
{
|
|
|
|
|
var rule = factory.CreateRule(FilterRuleType.Simplified);
|
2019-09-10 11:01:49 +02:00
|
|
|
|
|
2019-09-24 08:53:29 +02:00
|
|
|
|
rule.Initialize(new FilterRuleSettings { Expression = settings.StartUrl, Result = FilterResult.Allow });
|
|
|
|
|
requestFilter.Load(rule);
|
|
|
|
|
|
|
|
|
|
logger.Debug($"Automatically created filter rule to allow start URL '{settings.StartUrl}'.");
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-06 08:13:27 +02:00
|
|
|
|
}
|
2018-08-31 15:29:36 +02:00
|
|
|
|
|
2019-09-06 08:13:27 +02:00
|
|
|
|
private void InitializeWindow()
|
|
|
|
|
{
|
2019-01-23 09:37:47 +01:00
|
|
|
|
window = uiFactory.CreateBrowserWindow(control, settings, isMainInstance);
|
2019-11-29 14:59:54 +01:00
|
|
|
|
window.Closing += Window_Closing;
|
2017-07-31 20:22:53 +02:00
|
|
|
|
window.AddressChanged += Window_AddressChanged;
|
|
|
|
|
window.BackwardNavigationRequested += Window_BackwardNavigationRequested;
|
2019-05-22 11:42:31 +02:00
|
|
|
|
window.DeveloperConsoleRequested += Window_DeveloperConsoleRequested;
|
2020-08-10 21:42:51 +02:00
|
|
|
|
window.FindRequested += Window_FindRequested;
|
2017-07-31 20:22:53 +02:00
|
|
|
|
window.ForwardNavigationRequested += Window_ForwardNavigationRequested;
|
2019-05-22 11:42:31 +02:00
|
|
|
|
window.ReloadRequested += ReloadRequested;
|
2019-01-18 16:11:33 +01:00
|
|
|
|
window.ZoomInRequested += ZoomInRequested;
|
|
|
|
|
window.ZoomOutRequested += ZoomOutRequested;
|
|
|
|
|
window.ZoomResetRequested += ZoomResetRequested;
|
2019-05-22 11:42:31 +02:00
|
|
|
|
window.UpdateZoomLevel(CalculateZoomPercentage());
|
2019-08-30 12:30:00 +02:00
|
|
|
|
window.Show();
|
2018-08-31 15:29:36 +02:00
|
|
|
|
|
2019-12-05 11:54:43 +01:00
|
|
|
|
Handle = window.Handle;
|
|
|
|
|
|
2018-08-31 15:29:36 +02:00
|
|
|
|
logger.Debug("Initialized browser window.");
|
2017-07-31 20:22:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Control_AddressChanged(string address)
|
|
|
|
|
{
|
2019-01-17 11:12:17 +01:00
|
|
|
|
logger.Debug($"Navigated to '{address}'.");
|
2017-07-31 20:22:53 +02:00
|
|
|
|
window.UpdateAddress(address);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-15 16:13:15 +02:00
|
|
|
|
private void Control_LoadFailed(int errorCode, string errorText, string url)
|
|
|
|
|
{
|
|
|
|
|
if (errorCode == (int) CefErrorCode.None)
|
|
|
|
|
{
|
|
|
|
|
logger.Info($"Request for '{url}' was successful.");
|
|
|
|
|
}
|
|
|
|
|
else if (errorCode == (int) CefErrorCode.Aborted)
|
|
|
|
|
{
|
|
|
|
|
logger.Info($"Request for '{url}' was aborted.");
|
|
|
|
|
}
|
2020-08-06 14:26:40 +02:00
|
|
|
|
else if (errorCode == (int) CefErrorCode.UnknownUrlScheme)
|
|
|
|
|
{
|
|
|
|
|
logger.Info($"Request for '{url}' contains unknown URL scheme and will be handled by the OS.");
|
|
|
|
|
}
|
2020-05-15 16:13:15 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2020-08-06 14:30:37 +02:00
|
|
|
|
var title = text.Get(TextKey.Browser_LoadErrorTitle);
|
|
|
|
|
var message = text.Get(TextKey.Browser_LoadErrorMessage).Replace("%%URL%%", url) + $" {errorText} ({errorCode})";
|
2020-05-15 16:13:15 +02:00
|
|
|
|
|
|
|
|
|
logger.Warn($"Request for '{url}' failed: {errorText} ({errorCode}).");
|
|
|
|
|
|
|
|
|
|
Task.Run(() => messageBox.Show(message, title, icon: MessageBoxIcon.Error, parent: window)).ContinueWith(_ => control.NavigateBackwards());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-01 08:50:08 +01:00
|
|
|
|
private void Control_LoadingStateChanged(bool isLoading)
|
|
|
|
|
{
|
2019-01-23 09:37:47 +01:00
|
|
|
|
window.CanNavigateBackwards = WindowSettings.AllowBackwardNavigation && control.CanNavigateBackwards;
|
|
|
|
|
window.CanNavigateForwards = WindowSettings.AllowForwardNavigation && control.CanNavigateForwards;
|
2018-03-01 08:50:08 +01:00
|
|
|
|
window.UpdateLoadingState(isLoading);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-31 20:22:53 +02:00
|
|
|
|
private void Control_TitleChanged(string title)
|
|
|
|
|
{
|
2019-11-28 17:22:04 +01:00
|
|
|
|
Title = title;
|
|
|
|
|
window.UpdateTitle(Title);
|
|
|
|
|
TitleChanged?.Invoke(Title);
|
2017-07-31 20:22:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-20 16:13:08 +01:00
|
|
|
|
private void DialogHandler_DialogRequested(DialogRequestedEventArgs args)
|
|
|
|
|
{
|
2020-01-24 10:19:11 +01:00
|
|
|
|
var isDownload = args.Operation == FileSystemOperation.Save;
|
|
|
|
|
var isUpload = args.Operation == FileSystemOperation.Open;
|
|
|
|
|
var isAllowed = (isDownload && settings.AllowDownloads) || (isUpload && settings.AllowUploads);
|
2020-08-05 22:55:38 +02:00
|
|
|
|
var initialPath = default(string);
|
|
|
|
|
|
|
|
|
|
if (isDownload)
|
|
|
|
|
{
|
|
|
|
|
initialPath = args.InitialPath;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
initialPath = string.IsNullOrEmpty(settings.DownAndUploadDirectory) ? KnownFolders.Downloads.ExpandedPath : Environment.ExpandEnvironmentVariables(settings.DownAndUploadDirectory);
|
|
|
|
|
}
|
2020-01-20 16:13:08 +01:00
|
|
|
|
|
2020-01-24 10:19:11 +01:00
|
|
|
|
if (isAllowed)
|
2020-01-20 16:13:08 +01:00
|
|
|
|
{
|
2020-08-05 22:55:38 +02:00
|
|
|
|
var result = fileSystemDialog.Show(
|
|
|
|
|
args.Element,
|
|
|
|
|
args.Operation,
|
|
|
|
|
initialPath,
|
|
|
|
|
title: args.Title,
|
|
|
|
|
parent: window,
|
|
|
|
|
restrictNavigation: !settings.AllowCustomDownAndUploadLocation);
|
2020-01-24 10:19:11 +01:00
|
|
|
|
|
|
|
|
|
if (result.Success)
|
|
|
|
|
{
|
|
|
|
|
args.FullPath = result.FullPath;
|
|
|
|
|
args.Success = result.Success;
|
|
|
|
|
logger.Debug($"User selected path '{result.FullPath}' when asked to {args.Operation}->{args.Element}.");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Debug($"User aborted file system dialog to {args.Operation}->{args.Element}.");
|
|
|
|
|
}
|
2020-01-20 16:13:08 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-01-24 10:19:11 +01:00
|
|
|
|
logger.Info($"Blocked file system dialog to {args.Operation}->{args.Element}, as {(isDownload ? "downloading" : "uploading")} is not allowed.");
|
2020-01-20 16:13:08 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-17 16:15:10 +01:00
|
|
|
|
private void DisplayHandler_FaviconChanged(string uri)
|
|
|
|
|
{
|
2020-06-22 11:31:42 +02:00
|
|
|
|
Task.Run(() =>
|
2019-05-08 13:53:38 +02:00
|
|
|
|
{
|
2020-06-22 11:31:42 +02:00
|
|
|
|
var request = new HttpRequestMessage(HttpMethod.Head, uri);
|
|
|
|
|
var response = httpClient.SendAsync(request).ContinueWith(task =>
|
2019-05-08 13:53:38 +02:00
|
|
|
|
{
|
2020-06-22 11:31:42 +02:00
|
|
|
|
if (task.IsCompleted && task.Result.IsSuccessStatusCode)
|
|
|
|
|
{
|
|
|
|
|
Icon = new BrowserIconResource(uri);
|
|
|
|
|
|
|
|
|
|
IconChanged?.Invoke(Icon);
|
|
|
|
|
window.UpdateIcon(Icon);
|
|
|
|
|
}
|
|
|
|
|
});
|
2019-05-08 13:53:38 +02:00
|
|
|
|
});
|
2019-01-17 16:15:10 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 11:42:31 +02:00
|
|
|
|
private void DisplayHandler_ProgressChanged(double value)
|
|
|
|
|
{
|
|
|
|
|
window.UpdateProgress(value);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-30 11:24:28 +01:00
|
|
|
|
private void DownloadHandler_ConfigurationDownloadRequested(string fileName, DownloadEventArgs args)
|
|
|
|
|
{
|
2018-11-08 09:39:52 +01:00
|
|
|
|
if (settings.AllowConfigurationDownloads)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug($"Forwarding download request for configuration file '{fileName}'.");
|
|
|
|
|
ConfigurationDownloadRequested?.Invoke(fileName, args);
|
2019-09-04 15:12:59 +02:00
|
|
|
|
|
|
|
|
|
if (args.AllowDownload)
|
|
|
|
|
{
|
2019-09-25 08:45:20 +02:00
|
|
|
|
logger.Debug($"Download request for configuration file '{fileName}' was granted.");
|
2019-09-04 15:12:59 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Debug($"Download request for configuration file '{fileName}' was denied.");
|
|
|
|
|
messageBox.Show(TextKey.MessageBox_ReconfigurationDenied, TextKey.MessageBox_ReconfigurationDeniedTitle, parent: window);
|
|
|
|
|
}
|
2018-11-08 09:39:52 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Debug($"Discarded download request for configuration file '{fileName}'.");
|
|
|
|
|
}
|
2018-10-30 11:24:28 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-22 15:16:11 +01:00
|
|
|
|
private void DownloadHandler_DownloadUpdated(DownloadItemState state)
|
|
|
|
|
{
|
|
|
|
|
window.UpdateDownloadState(state);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-10 21:42:51 +02:00
|
|
|
|
private void KeyboardHandler_FindRequested()
|
|
|
|
|
{
|
2020-08-11 17:52:51 +02:00
|
|
|
|
if (settings.AllowFind)
|
|
|
|
|
{
|
|
|
|
|
window.ShowFindbar();
|
|
|
|
|
}
|
2020-08-10 21:42:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-17 11:12:17 +01:00
|
|
|
|
private void LifeSpanHandler_PopupRequested(PopupRequestedEventArgs args)
|
|
|
|
|
{
|
2019-12-13 16:10:10 +01:00
|
|
|
|
var validCurrentUri = Uri.TryCreate(control.Address, UriKind.Absolute, out var currentUri);
|
|
|
|
|
var validNewUri = Uri.TryCreate(args.Url, UriKind.Absolute, out var newUri);
|
|
|
|
|
var sameHost = validCurrentUri && validNewUri && string.Equals(currentUri.Host, newUri.Host, StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
2019-12-12 15:41:05 +01:00
|
|
|
|
switch (settings.PopupPolicy)
|
2019-01-17 11:12:17 +01:00
|
|
|
|
{
|
2019-12-12 15:41:05 +01:00
|
|
|
|
case PopupPolicy.Allow:
|
2019-12-13 16:10:10 +01:00
|
|
|
|
case PopupPolicy.AllowSameHost when sameHost:
|
2019-12-12 15:41:05 +01:00
|
|
|
|
logger.Debug($"Forwarding request to open new window for '{args.Url}'...");
|
|
|
|
|
PopupRequested?.Invoke(args);
|
|
|
|
|
break;
|
2019-12-13 16:10:10 +01:00
|
|
|
|
case PopupPolicy.AllowSameWindow:
|
|
|
|
|
case PopupPolicy.AllowSameHostAndWindow when sameHost:
|
2019-12-12 15:41:05 +01:00
|
|
|
|
logger.Info($"Discarding request to open new window and loading '{args.Url}' directly...");
|
|
|
|
|
control.NavigateTo(args.Url);
|
|
|
|
|
break;
|
2019-12-13 16:10:10 +01:00
|
|
|
|
case PopupPolicy.AllowSameHost when !sameHost:
|
|
|
|
|
case PopupPolicy.AllowSameHostAndWindow when !sameHost:
|
|
|
|
|
logger.Info($"Blocked request to open new window for '{args.Url}' as it targets a different host.");
|
|
|
|
|
break;
|
2019-12-12 15:41:05 +01:00
|
|
|
|
default:
|
2019-12-13 16:10:10 +01:00
|
|
|
|
logger.Info($"Blocked request to open new window for '{args.Url}'.");
|
2019-12-12 15:41:05 +01:00
|
|
|
|
break;
|
2019-01-17 11:12:17 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-19 15:02:40 +01:00
|
|
|
|
private void RequestHandler_QuitUrlVisited(string url)
|
|
|
|
|
{
|
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
2020-09-21 19:22:15 +02:00
|
|
|
|
if (settings.ResetOnQuitUrl)
|
2019-12-19 15:02:40 +01:00
|
|
|
|
{
|
2020-09-21 19:22:15 +02:00
|
|
|
|
logger.Info("Forwarding request to reset browser...");
|
|
|
|
|
ResetRequested?.Invoke();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (settings.ConfirmQuitUrl)
|
2019-12-19 15:02:40 +01:00
|
|
|
|
{
|
2020-09-21 19:22:15 +02:00
|
|
|
|
var message = text.Get(TextKey.MessageBox_BrowserQuitUrlConfirmation);
|
|
|
|
|
var title = text.Get(TextKey.MessageBox_BrowserQuitUrlConfirmationTitle);
|
|
|
|
|
var result = messageBox.Show(message, title, MessageBoxAction.YesNo, MessageBoxIcon.Question, window);
|
|
|
|
|
var terminate = result == MessageBoxResult.Yes;
|
|
|
|
|
|
|
|
|
|
if (terminate)
|
|
|
|
|
{
|
|
|
|
|
logger.Info($"User confirmed termination via quit URL '{url}', forwarding request...");
|
|
|
|
|
TerminationRequested?.Invoke();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Info($"User aborted termination via quit URL '{url}'.");
|
|
|
|
|
}
|
2019-12-19 15:02:40 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-09-21 19:22:15 +02:00
|
|
|
|
logger.Info($"Automatically requesting termination due to quit URL '{url}'...");
|
|
|
|
|
TerminationRequested?.Invoke();
|
2019-12-19 15:02:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 12:31:17 +02:00
|
|
|
|
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);
|
|
|
|
|
|
2019-09-24 08:53:29 +02:00
|
|
|
|
control.TitleChanged -= Control_TitleChanged;
|
|
|
|
|
|
2019-12-19 15:02:40 +01:00
|
|
|
|
if (url.Equals(startUrl, StringComparison.OrdinalIgnoreCase))
|
2019-09-24 08:53:29 +02:00
|
|
|
|
{
|
|
|
|
|
window.UpdateTitle($"*** {title} ***");
|
2019-11-28 17:22:04 +01:00
|
|
|
|
TitleChanged?.Invoke($"*** {title} ***");
|
2019-09-24 08:53:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 12:31:17 +02:00
|
|
|
|
messageBox.Show(message, title, parent: window);
|
2019-09-24 08:53:29 +02:00
|
|
|
|
control.TitleChanged += Control_TitleChanged;
|
2019-09-12 12:31:17 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 16:11:33 +01:00
|
|
|
|
private void ReloadRequested()
|
2017-07-31 20:22:53 +02:00
|
|
|
|
{
|
2019-01-23 09:37:47 +01:00
|
|
|
|
if (WindowSettings.AllowReloading && WindowSettings.ShowReloadWarning)
|
2019-01-18 16:11:33 +01:00
|
|
|
|
{
|
|
|
|
|
var result = messageBox.Show(TextKey.MessageBox_ReloadConfirmation, TextKey.MessageBox_ReloadConfirmationTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question, window);
|
|
|
|
|
|
|
|
|
|
if (result == MessageBoxResult.Yes)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("The user confirmed reloading the current page...");
|
|
|
|
|
control.Reload();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("The user aborted reloading the current page.");
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-23 09:37:47 +01:00
|
|
|
|
else if (WindowSettings.AllowReloading)
|
2019-01-18 16:11:33 +01:00
|
|
|
|
{
|
|
|
|
|
logger.Debug("Reloading current page...");
|
|
|
|
|
control.Reload();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Blocked reload attempt, as the user is not allowed to reload web pages.");
|
|
|
|
|
}
|
2017-07-31 20:22:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 16:11:33 +01:00
|
|
|
|
private void Window_AddressChanged(string address)
|
2017-07-31 20:22:53 +02:00
|
|
|
|
{
|
2019-03-15 15:55:34 +01:00
|
|
|
|
var isValid = Uri.TryCreate(address, UriKind.Absolute, out _) || Uri.TryCreate($"https://{address}", UriKind.Absolute, out _);
|
|
|
|
|
|
|
|
|
|
if (isValid)
|
|
|
|
|
{
|
|
|
|
|
logger.Debug($"The user requested to navigate to '{address}', the URI is valid.");
|
|
|
|
|
control.NavigateTo(address);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
logger.Debug($"The user requested to navigate to '{address}', but the URI is not valid.");
|
|
|
|
|
window.UpdateAddress(string.Empty);
|
|
|
|
|
}
|
2017-07-31 20:22:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Window_BackwardNavigationRequested()
|
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
logger.Debug("Navigating backwards...");
|
2017-07-31 20:22:53 +02:00
|
|
|
|
control.NavigateBackwards();
|
2017-07-14 10:28:59 +02:00
|
|
|
|
}
|
2017-07-24 17:31:28 +02:00
|
|
|
|
|
2019-11-29 14:59:54 +01:00
|
|
|
|
private void Window_Closing()
|
|
|
|
|
{
|
|
|
|
|
logger.Info($"Instance has terminated.");
|
2020-06-23 16:53:43 +02:00
|
|
|
|
control.Destroy();
|
2019-11-29 14:59:54 +01:00
|
|
|
|
Terminated?.Invoke(Id);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 11:42:31 +02:00
|
|
|
|
private void Window_DeveloperConsoleRequested()
|
|
|
|
|
{
|
|
|
|
|
logger.Debug("Showing developer console...");
|
|
|
|
|
control.ShowDeveloperConsole();
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-10 21:42:51 +02:00
|
|
|
|
private void Window_FindRequested(string term, bool isInitial, bool caseSensitive, bool forward = true)
|
|
|
|
|
{
|
2020-08-11 17:52:51 +02:00
|
|
|
|
if (settings.AllowFind)
|
|
|
|
|
{
|
|
|
|
|
control.Find(term, isInitial, caseSensitive, forward);
|
|
|
|
|
}
|
2020-08-10 21:42:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-31 20:22:53 +02:00
|
|
|
|
private void Window_ForwardNavigationRequested()
|
2017-07-24 17:31:28 +02:00
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
logger.Debug("Navigating forwards...");
|
2017-07-31 20:22:53 +02:00
|
|
|
|
control.NavigateForwards();
|
2017-07-24 17:31:28 +02:00
|
|
|
|
}
|
2019-01-18 16:11:33 +01:00
|
|
|
|
|
|
|
|
|
private void ZoomInRequested()
|
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
if (settings.AllowPageZoom && CalculateZoomPercentage() < 300)
|
2019-01-18 16:11:33 +01:00
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
zoomLevel += ZOOM_FACTOR;
|
|
|
|
|
control.Zoom(zoomLevel);
|
|
|
|
|
window.UpdateZoomLevel(CalculateZoomPercentage());
|
|
|
|
|
logger.Debug($"Increased page zoom to {CalculateZoomPercentage()}%.");
|
2019-01-18 16:11:33 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ZoomOutRequested()
|
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
if (settings.AllowPageZoom && CalculateZoomPercentage() > 25)
|
2019-01-18 16:11:33 +01:00
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
zoomLevel -= ZOOM_FACTOR;
|
|
|
|
|
control.Zoom(zoomLevel);
|
|
|
|
|
window.UpdateZoomLevel(CalculateZoomPercentage());
|
|
|
|
|
logger.Debug($"Decreased page zoom to {CalculateZoomPercentage()}%.");
|
2019-01-18 16:11:33 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ZoomResetRequested()
|
|
|
|
|
{
|
|
|
|
|
if (settings.AllowPageZoom)
|
|
|
|
|
{
|
2019-05-22 11:42:31 +02:00
|
|
|
|
zoomLevel = 0;
|
|
|
|
|
control.Zoom(0);
|
|
|
|
|
window.UpdateZoomLevel(CalculateZoomPercentage());
|
|
|
|
|
logger.Debug($"Reset page zoom to {CalculateZoomPercentage()}%.");
|
2019-01-18 16:11:33 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-22 11:42:31 +02:00
|
|
|
|
|
|
|
|
|
private double CalculateZoomPercentage()
|
|
|
|
|
{
|
|
|
|
|
return (zoomLevel * 25.0) + 100.0;
|
|
|
|
|
}
|
2017-07-14 10:28:59 +02:00
|
|
|
|
}
|
|
|
|
|
}
|