SEBWIN-531, #240: Refactored browser application instance to browser window.

This commit is contained in:
Damian Büchel 2022-02-04 13:41:11 +01:00
parent fa3763a32a
commit 83c387cffd
4 changed files with 70 additions and 65 deletions

View file

@ -37,12 +37,11 @@ namespace SafeExamBrowser.Browser
{
public class BrowserApplication : IBrowserApplication
{
private int instanceIdCounter = default(int);
private int windowIdCounter = default;
private readonly AppConfig appConfig;
private readonly IFileSystemDialog fileSystemDialog;
private readonly IHashAlgorithm hashAlgorithm;
private readonly List<BrowserApplicationInstance> instances;
private readonly IKeyGenerator keyGenerator;
private readonly IModuleLogger logger;
private readonly IMessageBox messageBox;
@ -50,6 +49,7 @@ namespace SafeExamBrowser.Browser
private readonly BrowserSettings settings;
private readonly IText text;
private readonly IUserInterfaceFactory uiFactory;
private readonly List<BrowserWindow> windows;
public bool AutoStart { get; private set; }
public IconResource Icon { get; private set; }
@ -77,7 +77,6 @@ namespace SafeExamBrowser.Browser
this.appConfig = appConfig;
this.fileSystemDialog = fileSystemDialog;
this.hashAlgorithm = hashAlgorithm;
this.instances = new List<BrowserApplicationInstance>();
this.keyGenerator = keyGenerator;
this.logger = logger;
this.messageBox = messageBox;
@ -85,11 +84,12 @@ namespace SafeExamBrowser.Browser
this.settings = settings;
this.text = text;
this.uiFactory = uiFactory;
this.windows = new List<BrowserWindow>();
}
public IEnumerable<IApplicationWindow> GetWindows()
{
return new List<IApplicationWindow>(instances);
return new List<IApplicationWindow>(windows);
}
public void Initialize()
@ -123,7 +123,7 @@ namespace SafeExamBrowser.Browser
public void Start()
{
CreateNewInstance();
CreateNewWindow();
}
public void Terminate()
@ -131,11 +131,11 @@ namespace SafeExamBrowser.Browser
logger.Info("Initiating termination...");
AwaitReady();
foreach (var instance in instances)
foreach (var window in windows)
{
instance.Terminated -= Instance_Terminated;
instance.Terminate();
logger.Info($"Terminated browser instance {instance.Id}.");
window.Closed -= Window_Closed;
window.Close();
logger.Info($"Closed browser window #{window.Id}.");
}
if (settings.UseTemporaryDownAndUploadDirectory)
@ -170,37 +170,37 @@ namespace SafeExamBrowser.Browser
Thread.Sleep(500);
}
private void CreateNewInstance(string url = null)
private void CreateNewWindow(string url = null)
{
var id = ++instanceIdCounter;
var isMainInstance = instances.Count == 0;
var instanceLogger = logger.CloneFor($"Browser Instance #{id}");
var id = ++windowIdCounter;
var isMainWindow = windows.Count == 0;
var startUrl = url ?? GenerateStartUrl();
var instance = new BrowserApplicationInstance(
var windowLogger = logger.CloneFor($"Browser Window #{id}");
var window = new BrowserWindow(
appConfig,
settings,
id,
isMainInstance,
isMainWindow,
fileSystemDialog,
hashAlgorithm,
keyGenerator,
messageBox,
instanceLogger,
windowLogger,
text,
uiFactory,
startUrl);
instance.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args);
instance.PopupRequested += Instance_PopupRequested;
instance.ResetRequested += Instance_ResetRequested;
instance.SessionIdentifierDetected += (i) => SessionIdentifierDetected?.Invoke(i);
instance.Terminated += Instance_Terminated;
instance.TerminationRequested += () => TerminationRequested?.Invoke();
window.Closed += Window_Closed;
window.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args);
window.PopupRequested += Window_PopupRequested;
window.ResetRequested += Window_ResetRequested;
window.SessionIdentifierDetected += (i) => SessionIdentifierDetected?.Invoke(i);
window.TerminationRequested += () => TerminationRequested?.Invoke();
instance.Initialize();
instances.Add(instance);
window.Initialize();
windows.Add(window);
logger.Info($"Created browser instance {instance.Id}.");
logger.Info($"Created browser window #{window.Id}.");
WindowsChanged?.Invoke();
}
@ -412,25 +412,32 @@ namespace SafeExamBrowser.Browser
throw new NotImplementedException($"Mapping for proxy protocol '{protocol}' is not yet implemented!");
}
private void Instance_PopupRequested(PopupRequestedEventArgs args)
private void Window_Closed(int id)
{
logger.Info($"Received request to create new instance{(settings.AdditionalWindow.UrlPolicy.CanLog() ? $" for '{args.Url}'" : "")}...");
CreateNewInstance(args.Url);
windows.Remove(windows.First(i => i.Id == id));
WindowsChanged?.Invoke();
logger.Info($"Window #{id} has been closed.");
}
private void Instance_ResetRequested()
private void Window_PopupRequested(PopupRequestedEventArgs args)
{
logger.Info($"Received request to create new window{(settings.AdditionalWindow.UrlPolicy.CanLog() ? $" for '{args.Url}'" : "")}...");
CreateNewWindow(args.Url);
}
private void Window_ResetRequested()
{
logger.Info("Attempting to reset browser...");
AwaitReady();
foreach (var instance in instances)
foreach (var window in windows)
{
instance.Terminated -= Instance_Terminated;
instance.Terminate();
logger.Info($"Terminated browser instance {instance.Id}.");
window.Closed -= Window_Closed;
window.Close();
logger.Info($"Closed browser window #{window.Id}.");
}
instances.Clear();
windows.Clear();
WindowsChanged?.Invoke();
if (settings.DeleteCookiesOnStartup && settings.DeleteCookiesOnShutdown)
@ -439,14 +446,8 @@ namespace SafeExamBrowser.Browser
}
nativeMethods.EmptyClipboard();
CreateNewInstance();
CreateNewWindow();
logger.Info("Successfully reset browser.");
}
private void Instance_Terminated(int id)
{
instances.Remove(instances.First(i => i.Id == id));
WindowsChanged?.Invoke();
}
}
}

View file

@ -37,7 +37,7 @@ using TitleChangedEventHandler = SafeExamBrowser.Applications.Contracts.Events.T
namespace SafeExamBrowser.Browser
{
internal class BrowserApplicationInstance : IApplicationWindow
internal class BrowserWindow : IApplicationWindow
{
private const double ZOOM_FACTOR = 0.2;
@ -45,22 +45,22 @@ namespace SafeExamBrowser.Browser
private readonly IFileSystemDialog fileSystemDialog;
private readonly IHashAlgorithm hashAlgorithm;
private readonly HttpClient httpClient;
private readonly bool isMainWindow;
private readonly IKeyGenerator keyGenerator;
private readonly IModuleLogger logger;
private readonly IMessageBox messageBox;
private readonly BrowserSettings settings;
private readonly string startUrl;
private readonly IText text;
private readonly IUserInterfaceFactory uiFactory;
private IBrowserControl control;
private IBrowserWindow window;
private bool isMainInstance;
private BrowserSettings settings;
private string startUrl;
private double zoomLevel;
private WindowSettings WindowSettings
{
get { return isMainInstance ? settings.MainWindow : settings.AdditionalWindow; }
get { return isMainWindow ? settings.MainWindow : settings.AdditionalWindow; }
}
internal int Id { get; }
@ -69,21 +69,21 @@ namespace SafeExamBrowser.Browser
public IconResource Icon { get; private set; }
public string Title { get; private set; }
internal event WindowClosedEventHandler Closed;
internal event DownloadRequestedEventHandler ConfigurationDownloadRequested;
internal event PopupRequestedEventHandler PopupRequested;
internal event ResetRequestedEventHandler ResetRequested;
internal event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
internal event InstanceTerminatedEventHandler Terminated;
internal event TerminationRequestedEventHandler TerminationRequested;
public event IconChangedEventHandler IconChanged;
public event TitleChangedEventHandler TitleChanged;
public BrowserApplicationInstance(
public BrowserWindow(
AppConfig appConfig,
BrowserSettings settings,
int id,
bool isMainInstance,
bool isMainWindow,
IFileSystemDialog fileSystemDialog,
IHashAlgorithm hashAlgorithm,
IKeyGenerator keyGenerator,
@ -96,7 +96,7 @@ namespace SafeExamBrowser.Browser
this.appConfig = appConfig;
this.Id = id;
this.httpClient = new HttpClient();
this.isMainInstance = isMainInstance;
this.isMainWindow = isMainWindow;
this.fileSystemDialog = fileSystemDialog;
this.hashAlgorithm = hashAlgorithm;
this.keyGenerator = keyGenerator;
@ -113,18 +113,18 @@ namespace SafeExamBrowser.Browser
window.BringToForeground();
}
internal void Close()
{
window.Close();
control.Destroy();
}
internal void Initialize()
{
InitializeControl();
InitializeWindow();
}
internal void Terminate()
{
window.Close();
control.Destroy();
}
private void InitializeControl()
{
var contextMenuHandler = new ContextMenuHandler();
@ -210,10 +210,10 @@ namespace SafeExamBrowser.Browser
private void InitializeWindow()
{
window = uiFactory.CreateBrowserWindow(control, settings, isMainInstance);
window.Closing += Window_Closing;
window = uiFactory.CreateBrowserWindow(control, settings, isMainWindow);
window.AddressChanged += Window_AddressChanged;
window.BackwardNavigationRequested += Window_BackwardNavigationRequested;
window.Closing += Window_Closing;
window.DeveloperConsoleRequested += Window_DeveloperConsoleRequested;
window.FindRequested += Window_FindRequested;
window.ForwardNavigationRequested += Window_ForwardNavigationRequested;
@ -297,9 +297,13 @@ namespace SafeExamBrowser.Browser
{
initialPath = args.InitialPath;
}
else if (string.IsNullOrEmpty(settings.DownAndUploadDirectory))
{
initialPath = KnownFolders.Downloads.ExpandedPath;
}
else
{
initialPath = string.IsNullOrEmpty(settings.DownAndUploadDirectory) ? KnownFolders.Downloads.ExpandedPath : Environment.ExpandEnvironmentVariables(settings.DownAndUploadDirectory);
initialPath = Environment.ExpandEnvironmentVariables(settings.DownAndUploadDirectory);
}
if (isAllowed)
@ -382,7 +386,7 @@ namespace SafeExamBrowser.Browser
private void HomeNavigationRequested()
{
if (isMainInstance && (settings.UseStartUrlAsHomeUrl || !string.IsNullOrWhiteSpace(settings.HomeUrl)))
if (isMainWindow && (settings.UseStartUrlAsHomeUrl || !string.IsNullOrWhiteSpace(settings.HomeUrl)))
{
var navigate = false;
var url = settings.UseStartUrlAsHomeUrl ? settings.StartUrl : settings.HomeUrl;
@ -568,9 +572,9 @@ namespace SafeExamBrowser.Browser
private void Window_Closing()
{
logger.Info($"Instance has terminated.");
logger.Info($"Window is closing...");
control.Destroy();
Terminated?.Invoke(Id);
Closed?.Invoke(Id);
}
private void Window_DeveloperConsoleRequested()

View file

@ -8,5 +8,5 @@
namespace SafeExamBrowser.Browser.Events
{
internal delegate void InstanceTerminatedEventHandler(int id);
internal delegate void WindowClosedEventHandler(int id);
}

View file

@ -79,12 +79,12 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BrowserApplication.cs" />
<Compile Include="BrowserApplicationInstance.cs" />
<Compile Include="BrowserWindow.cs" />
<Compile Include="Events\DialogRequestedEventArgs.cs" />
<Compile Include="Events\DialogRequestedEventHandler.cs" />
<Compile Include="Events\DownloadUpdatedEventHandler.cs" />
<Compile Include="Events\FaviconChangedEventHandler.cs" />
<Compile Include="Events\InstanceTerminatedEventHandler.cs" />
<Compile Include="Events\WindowClosedEventHandler.cs" />
<Compile Include="Events\PopupRequestedEventArgs.cs" />
<Compile Include="Events\PopupRequestedEventHandler.cs" />
<Compile Include="Events\ProgressChangedEventHandler.cs" />