diff --git a/SafeExamBrowser.Applications.Contracts/Events/InstanceStartedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/InstanceStartedEventHandler.cs new file mode 100644 index 00000000..c9e65009 --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/Events/InstanceStartedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +namespace SafeExamBrowser.Applications.Contracts.Events +{ + /// + /// Event handler used to inform about the existence of a new . + /// + public delegate void InstanceStartedEventHandler(IApplicationInstance instance); +} diff --git a/SafeExamBrowser.Applications.Contracts/Events/InstanceTerminatedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/InstanceTerminatedEventHandler.cs index f5b021ef..c108238c 100644 --- a/SafeExamBrowser.Applications.Contracts/Events/InstanceTerminatedEventHandler.cs +++ b/SafeExamBrowser.Applications.Contracts/Events/InstanceTerminatedEventHandler.cs @@ -11,7 +11,7 @@ using SafeExamBrowser.Core.Contracts; namespace SafeExamBrowser.Applications.Contracts.Events { /// - /// Event handler used to indicate that an with a particular ID has terminated. + /// Event handler used to indicate that an has terminated. /// public delegate void InstanceTerminatedEventHandler(InstanceIdentifier id); } diff --git a/SafeExamBrowser.Applications.Contracts/IApplicationController.cs b/SafeExamBrowser.Applications.Contracts/IApplication.cs similarity index 67% rename from SafeExamBrowser.Applications.Contracts/IApplicationController.cs rename to SafeExamBrowser.Applications.Contracts/IApplication.cs index 00acfebc..c0a5b705 100644 --- a/SafeExamBrowser.Applications.Contracts/IApplicationController.cs +++ b/SafeExamBrowser.Applications.Contracts/IApplication.cs @@ -6,24 +6,30 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using SafeExamBrowser.Applications.Contracts.Events; + namespace SafeExamBrowser.Applications.Contracts { /// - /// Controls the lifetime and functionality of a (third-party) application which can be accessed via the . + /// Controls the lifetime and functionality of a (third-party) application. /// - public interface IApplicationController + public interface IApplication { + /// + /// Provides information about the application. + /// + IApplicationInfo Info { get; } + + /// + /// Fired when a new has started. + /// + event InstanceStartedEventHandler InstanceStarted; + /// /// Performs any initialization work, if necessary. /// void Initialize(); - // TODO - ///// - ///// Registers an application control for this application. - ///// - //void RegisterApplicationControl(IApplicationControl control); - /// /// Starts the execution of the application. /// diff --git a/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs b/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs index 6b150b7e..a9cef522 100644 --- a/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs +++ b/SafeExamBrowser.Applications.Contracts/IApplicationInstance.cs @@ -22,7 +22,7 @@ namespace SafeExamBrowser.Applications.Contracts InstanceIdentifier Id { get; } /// - /// The name or (document) title of the application instance. + /// The name or document title of the application instance. /// string Name { get; } @@ -41,10 +41,9 @@ namespace SafeExamBrowser.Applications.Contracts /// event NameChangedEventHandler NameChanged; - // TODO - ///// - ///// The main window of the application instance. - ///// - //IWindow Window { get; } + /// + /// Makes this instance the currently active one and brings it to the foreground. + /// + void Activate(); } } diff --git a/SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj b/SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj index b617f62d..7a105561 100644 --- a/SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj +++ b/SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj @@ -54,9 +54,10 @@ + - + diff --git a/SafeExamBrowser.Browser.Contracts/IBrowserApplicationController.cs b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs similarity index 90% rename from SafeExamBrowser.Browser.Contracts/IBrowserApplicationController.cs rename to SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs index 3b62f849..40e259cd 100644 --- a/SafeExamBrowser.Browser.Contracts/IBrowserApplicationController.cs +++ b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs @@ -13,7 +13,7 @@ namespace SafeExamBrowser.Browser.Contracts /// /// Controls the lifetime and functionality of the browser application. /// - public interface IBrowserApplicationController : IApplicationController + public interface IBrowserApplication : IApplication { /// /// Event fired when the browser application detects a download request for an application configuration file. diff --git a/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj index 5558de35..9b696f19 100644 --- a/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj +++ b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj @@ -56,7 +56,7 @@ - + diff --git a/SafeExamBrowser.Browser/BrowserApplicationController.cs b/SafeExamBrowser.Browser/BrowserApplication.cs similarity index 80% rename from SafeExamBrowser.Browser/BrowserApplicationController.cs rename to SafeExamBrowser.Browser/BrowserApplication.cs index 333b8c9b..47d9ac0a 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationController.cs +++ b/SafeExamBrowser.Browser/BrowserApplication.cs @@ -12,6 +12,7 @@ using System.Linq; using CefSharp; using CefSharp.WinForms; using SafeExamBrowser.Applications.Contracts; +using SafeExamBrowser.Applications.Contracts.Events; using SafeExamBrowser.Browser.Contracts; using SafeExamBrowser.Browser.Events; using SafeExamBrowser.Configuration.Contracts; @@ -20,27 +21,28 @@ using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts.MessageBox; -using SafeExamBrowser.UserInterface.Contracts.Shell; using BrowserSettings = SafeExamBrowser.Configuration.Contracts.Settings.BrowserSettings; namespace SafeExamBrowser.Browser { - public class BrowserApplicationController : IBrowserApplicationController + public class BrowserApplication : IBrowserApplication { private int instanceIdCounter = default(int); private AppConfig appConfig; - private IList controls; - private IList instances; + private List instances; private IMessageBox messageBox; private IModuleLogger logger; private BrowserSettings settings; private IText text; private IUserInterfaceFactory uiFactory; - public event DownloadRequestedEventHandler ConfigurationDownloadRequested; + public IApplicationInfo Info { get; private set; } - public BrowserApplicationController( + public event DownloadRequestedEventHandler ConfigurationDownloadRequested; + public event InstanceStartedEventHandler InstanceStarted; + + public BrowserApplication( AppConfig appConfig, BrowserSettings settings, IMessageBox messageBox, @@ -49,8 +51,7 @@ namespace SafeExamBrowser.Browser IUserInterfaceFactory uiFactory) { this.appConfig = appConfig; - this.controls = new List(); - this.instances = new List(); + this.instances = new List(); this.logger = logger; this.messageBox = messageBox; this.settings = settings; @@ -63,20 +64,18 @@ namespace SafeExamBrowser.Browser var cefSettings = InitializeCefSettings(); var success = Cef.Initialize(cefSettings, true, default(IApp)); - logger.Info("Initialized browser."); + Info = new BrowserApplicationInfo(); - if (!success) + if (success) + { + logger.Info("Initialized browser."); + } + else { throw new Exception("Failed to initialize browser!"); } } - public void RegisterApplicationControl(IApplicationControl control) - { - control.Clicked += ApplicationControl_Clicked; - controls.Add(control); - } - public void Start() { CreateNewInstance(); @@ -87,13 +86,11 @@ namespace SafeExamBrowser.Browser foreach (var instance in instances) { instance.Terminated -= Instance_Terminated; - // TODO instance.Window.Close(); - + instance.Terminate(); logger.Info($"Terminated browser instance {instance.Id}."); } Cef.Shutdown(); - logger.Info("Terminated browser."); } @@ -105,35 +102,17 @@ namespace SafeExamBrowser.Browser var startUrl = url ?? settings.StartUrl; var instance = new BrowserApplicationInstance(appConfig, settings, id, isMainInstance, messageBox, instanceLogger, text, uiFactory, startUrl); - instance.Initialize(); instance.ConfigurationDownloadRequested += (fileName, args) => ConfigurationDownloadRequested?.Invoke(fileName, args); - instance.IconChanged += Instance_IconChanged; - instance.NameChanged += Instance_NameChanged; instance.PopupRequested += Instance_PopupRequested; instance.Terminated += Instance_Terminated; + instance.Initialize(); instances.Add(instance); - instance.Window.Show(); + InstanceStarted?.Invoke(instance); logger.Info($"Created browser instance {instance.Id}."); } - private void Instance_NameChanged(string name) - { - foreach (var control in controls) - { - // TODO - } - } - - private void Instance_IconChanged(IIconResource icon) - { - foreach (var control in controls) - { - // TODO - } - } - private CefSettings InitializeCefSettings() { var warning = logger.LogLevel == LogLevel.Warning; @@ -156,18 +135,6 @@ namespace SafeExamBrowser.Browser return cefSettings; } - private void ApplicationControl_Clicked(InstanceIdentifier id = null) - { - if (id == null) - { - CreateNewInstance(); - } - else - { - // TODO instances.FirstOrDefault(i => i.Id == id)?.Window?.BringToForeground(); - } - } - private void Instance_PopupRequested(PopupRequestedEventArgs args) { logger.Info($"Received request to create new instance for '{args.Url}'..."); diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs index 28429764..1eef020a 100644 --- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs +++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs @@ -21,7 +21,6 @@ using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts.Browser; using SafeExamBrowser.UserInterface.Contracts.MessageBox; -using SafeExamBrowser.UserInterface.Contracts.Windows; namespace SafeExamBrowser.Browser { @@ -49,7 +48,6 @@ namespace SafeExamBrowser.Browser public InstanceIdentifier Id { get; private set; } public string Name { get; private set; } - public IWindow Window { get { return window; } } public event DownloadRequestedEventHandler ConfigurationDownloadRequested; public event IconChangedEventHandler IconChanged; @@ -80,6 +78,11 @@ namespace SafeExamBrowser.Browser this.url = url; } + public void Activate() + { + window?.BringToForeground(); + } + internal void Initialize() { var contextMenuHandler = new ContextMenuHandler(); @@ -118,10 +121,16 @@ namespace SafeExamBrowser.Browser window.ZoomOutRequested += ZoomOutRequested; window.ZoomResetRequested += ZoomResetRequested; window.UpdateZoomLevel(CalculateZoomPercentage()); + window.Show(); logger.Debug("Initialized browser window."); } + internal void Terminate() + { + window?.Close(); + } + private void Control_AddressChanged(string address) { logger.Debug($"Navigated to '{address}'."); diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj index 912f62f7..0cc1430c 100644 --- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj +++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj @@ -64,7 +64,7 @@ - + diff --git a/SafeExamBrowser.Client.Contracts/IClientController.cs b/SafeExamBrowser.Client.Contracts/IClientController.cs index b4a920c6..9401544c 100644 --- a/SafeExamBrowser.Client.Contracts/IClientController.cs +++ b/SafeExamBrowser.Client.Contracts/IClientController.cs @@ -25,9 +25,9 @@ namespace SafeExamBrowser.Client.Contracts AppConfig AppConfig { set; } /// - /// The controller for the browser application. + /// The browser application. /// - IBrowserApplicationController Browser { set; } + IBrowserApplication Browser { set; } /// /// The client host used for communication handling. diff --git a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs index 40c25a01..97b251e4 100644 --- a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs +++ b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs @@ -35,7 +35,7 @@ namespace SafeExamBrowser.Client.UnitTests { private AppConfig appConfig; private Mock actionCenter; - private Mock browserController; + private Mock browserController; private Mock clientHost; private Mock displayMonitor; private Mock explorerShell; @@ -61,7 +61,7 @@ namespace SafeExamBrowser.Client.UnitTests { appConfig = new AppConfig(); actionCenter = new Mock(); - browserController = new Mock(); + browserController = new Mock(); clientHost = new Mock(); displayMonitor = new Mock(); explorerShell = new Mock(); diff --git a/SafeExamBrowser.Client.UnitTests/Operations/BrowserOperationTests.cs b/SafeExamBrowser.Client.UnitTests/Operations/BrowserOperationTests.cs index 9f03d6e3..fd333667 100644 --- a/SafeExamBrowser.Client.UnitTests/Operations/BrowserOperationTests.cs +++ b/SafeExamBrowser.Client.UnitTests/Operations/BrowserOperationTests.cs @@ -20,8 +20,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations public class BrowserOperationTests { private Mock actionCenter; - private Mock controller; - private Mock appInfo; + private Mock application; private Mock logger; private Mock taskbar; private Mock uiFactory; @@ -32,13 +31,12 @@ namespace SafeExamBrowser.Client.UnitTests.Operations public void Initialize() { actionCenter = new Mock(); - controller = new Mock(); - appInfo = new Mock(); + application = new Mock(); logger = new Mock(); taskbar = new Mock(); uiFactory = new Mock(); - sut = new BrowserOperation(actionCenter.Object, controller.Object, appInfo.Object, logger.Object, taskbar.Object, uiFactory.Object); + sut = new BrowserOperation(actionCenter.Object, application.Object, logger.Object, taskbar.Object, uiFactory.Object); } [TestMethod] @@ -46,7 +44,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations { sut.Perform(); - controller.Verify(c => c.Initialize(), Times.Once); + application.Verify(c => c.Initialize(), Times.Once); // TODO controller.Verify(c => c.RegisterApplicationControl(It.IsAny()), Times.Exactly(2)); actionCenter.Verify(a => a.AddApplicationControl(It.IsAny()), Times.Once); taskbar.Verify(t => t.AddApplicationControl(It.IsAny()), Times.Once); @@ -56,7 +54,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations public void MustRevertCorrectly() { sut.Revert(); - controller.Verify(c => c.Terminate(), Times.Once); + application.Verify(c => c.Terminate(), Times.Once); } } } diff --git a/SafeExamBrowser.Client/ClientController.cs b/SafeExamBrowser.Client/ClientController.cs index 24dbdc83..a36d6214 100644 --- a/SafeExamBrowser.Client/ClientController.cs +++ b/SafeExamBrowser.Client/ClientController.cs @@ -50,7 +50,7 @@ namespace SafeExamBrowser.Client private IWindowMonitor windowMonitor; private AppConfig appConfig; - public IBrowserApplicationController Browser { private get; set; } + public IBrowserApplication Browser { private get; set; } public IClientHost ClientHost { private get; set; } public Guid SessionId { private get; set; } public Settings Settings { private get; set; } diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index 166ebe81..707421b2 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -60,7 +60,7 @@ namespace SafeExamBrowser.Client private UserInterfaceMode uiMode; private IActionCenter actionCenter; - private IBrowserApplicationController browserController; + private IBrowserApplication browser; private IClientHost clientHost; private ILogger logger; private IMessageBox messageBox; @@ -199,11 +199,11 @@ namespace SafeExamBrowser.Client private IOperation BuildBrowserOperation() { var moduleLogger = new ModuleLogger(logger, "BrowserController"); - var browserController = new BrowserApplicationController(configuration.AppConfig, configuration.Settings.Browser, messageBox, moduleLogger, text, uiFactory); + var browser = new BrowserApplication(configuration.AppConfig, configuration.Settings.Browser, messageBox, moduleLogger, text, uiFactory); var browserInfo = new BrowserApplicationInfo(); - var operation = new BrowserOperation(actionCenter, browserController, browserInfo, logger, taskbar, uiFactory); + var operation = new BrowserOperation(actionCenter, browser, logger, taskbar, uiFactory); - this.browserController = browserController; + this.browser = browser; return operation; } @@ -346,7 +346,7 @@ namespace SafeExamBrowser.Client private void UpdateClientControllerDependencies() { - ClientController.Browser = browserController; + ClientController.Browser = browser; ClientController.ClientHost = clientHost; ClientController.SessionId = configuration.SessionId; ClientController.Settings = configuration.Settings; diff --git a/SafeExamBrowser.Client/Operations/BrowserOperation.cs b/SafeExamBrowser.Client/Operations/BrowserOperation.cs index ca99d6ab..dc062a5f 100644 --- a/SafeExamBrowser.Client/Operations/BrowserOperation.cs +++ b/SafeExamBrowser.Client/Operations/BrowserOperation.cs @@ -19,8 +19,7 @@ namespace SafeExamBrowser.Client.Operations internal class BrowserOperation : IOperation { private IActionCenter actionCenter; - private IApplicationController browserController; - private IApplicationInfo browserInfo; + private IApplication browser; private ILogger logger; private ITaskbar taskbar; private IUserInterfaceFactory uiFactory; @@ -30,15 +29,13 @@ namespace SafeExamBrowser.Client.Operations public BrowserOperation( IActionCenter actionCenter, - IApplicationController browserController, - IApplicationInfo browserInfo, + IApplication browser, ILogger logger, ITaskbar taskbar, IUserInterfaceFactory uiFactory) { this.actionCenter = actionCenter; - this.browserController = browserController; - this.browserInfo = browserInfo; + this.browser = browser; this.logger = logger; this.taskbar = taskbar; this.uiFactory = uiFactory; @@ -49,16 +46,10 @@ namespace SafeExamBrowser.Client.Operations logger.Info("Initializing browser..."); StatusChanged?.Invoke(TextKey.OperationStatus_InitializeBrowser); - var actionCenterControl = uiFactory.CreateApplicationControl(browserInfo, Location.ActionCenter); - var taskbarControl = uiFactory.CreateApplicationControl(browserInfo, Location.Taskbar); + browser.Initialize(); - browserController.Initialize(); - // TODO - //browserController.RegisterApplicationControl(actionCenterControl); - //browserController.RegisterApplicationControl(taskbarControl); - - actionCenter.AddApplicationControl(actionCenterControl); - taskbar.AddApplicationControl(taskbarControl); + actionCenter.AddApplicationControl(uiFactory.CreateApplicationControl(browser, Location.ActionCenter)); + taskbar.AddApplicationControl(uiFactory.CreateApplicationControl(browser, Location.Taskbar)); return OperationResult.Success; } @@ -68,7 +59,7 @@ namespace SafeExamBrowser.Client.Operations logger.Info("Terminating browser..."); StatusChanged?.Invoke(TextKey.OperationStatus_TerminateBrowser); - browserController.Terminate(); + browser.Terminate(); return OperationResult.Success; } diff --git a/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs b/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs index b7eecd71..8dfdf627 100644 --- a/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs +++ b/SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs @@ -29,9 +29,9 @@ namespace SafeExamBrowser.UserInterface.Contracts IWindow CreateAboutWindow(AppConfig appConfig); /// - /// Creates an application control for the specified location, initialized with the given application information. + /// Creates an application control for the specified application and location. /// - IApplicationControl CreateApplicationControl(IApplicationInfo info, Location location); + IApplicationControl CreateApplicationControl(IApplication application, Location location); /// /// Creates a system control which allows to change the audio settings of the computer. diff --git a/SafeExamBrowser.UserInterface.Contracts/Shell/IApplicationControl.cs b/SafeExamBrowser.UserInterface.Contracts/Shell/IApplicationControl.cs index 7a125f0c..b9d3feb6 100644 --- a/SafeExamBrowser.UserInterface.Contracts/Shell/IApplicationControl.cs +++ b/SafeExamBrowser.UserInterface.Contracts/Shell/IApplicationControl.cs @@ -6,8 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using SafeExamBrowser.UserInterface.Contracts.Shell.Events; - namespace SafeExamBrowser.UserInterface.Contracts.Shell { /// @@ -15,10 +13,5 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell /// public interface IApplicationControl { - /// - /// Event fired when the user clicked on the application control. If multiple instances of an application are active, - /// the handler should only executed when the user selects one of the instances. - /// - event ApplicationControlClickedEventHandler Clicked; } } diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml index 555c132f..627c5f4d 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterApplicationButton.xaml @@ -14,7 +14,7 @@ -