diff --git a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
index 66700cd8..8aaf52f4 100644
--- a/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
+++ b/SafeExamBrowser.Browser/BrowserApplicationInstance.cs
@@ -39,6 +39,7 @@ namespace SafeExamBrowser.Browser
public IWindow Window { get { return window; } }
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
+ public event IconChangedEventHandler IconChanged;
public event InstanceTerminatedEventHandler Terminated;
public event NameChangedEventHandler NameChanged;
public event PopupRequestedEventHandler PopupRequested;
@@ -66,17 +67,19 @@ namespace SafeExamBrowser.Browser
internal void Initialize()
{
var contextMenuHandler = new ContextMenuHandler(settings, text);
+ var displayHandler = new DisplayHandler();
var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} {Id}");
var downloadHandler = new DownloadHandler(appConfig, settings, downloadLogger);
var keyboardHandler = new KeyboardHandler();
var lifeSpanHandler = new LifeSpanHandler();
var requestHandler = new RequestHandler(appConfig);
+ displayHandler.FaviconChanged += DisplayHandler_FaviconChanged;
downloadHandler.ConfigurationDownloadRequested += DownloadHandler_ConfigurationDownloadRequested;
keyboardHandler.ReloadRequested += KeyboardHandler_ReloadRequested;
lifeSpanHandler.PopupRequested += LifeSpanHandler_PopupRequested;
- control = new BrowserControl(contextMenuHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, settings.StartUrl);
+ control = new BrowserControl(contextMenuHandler, displayHandler, downloadHandler, keyboardHandler, lifeSpanHandler, requestHandler, settings.StartUrl);
control.AddressChanged += Control_AddressChanged;
control.LoadingStateChanged += Control_LoadingStateChanged;
control.TitleChanged += Control_TitleChanged;
@@ -139,6 +142,14 @@ namespace SafeExamBrowser.Browser
NameChanged?.Invoke(title);
}
+ private void DisplayHandler_FaviconChanged(string uri)
+ {
+ var icon = new BrowserIconResource(uri);
+
+ IconChanged?.Invoke(icon);
+ window.UpdateIcon(icon);
+ }
+
private void DownloadHandler_ConfigurationDownloadRequested(string fileName, DownloadEventArgs args)
{
if (settings.AllowConfigurationDownloads)
diff --git a/SafeExamBrowser.Browser/BrowserControl.cs b/SafeExamBrowser.Browser/BrowserControl.cs
index 01f22a77..994ca66c 100644
--- a/SafeExamBrowser.Browser/BrowserControl.cs
+++ b/SafeExamBrowser.Browser/BrowserControl.cs
@@ -16,6 +16,7 @@ namespace SafeExamBrowser.Browser
internal class BrowserControl : ChromiumWebBrowser, IBrowserControl
{
private IContextMenuHandler contextMenuHandler;
+ private IDisplayHandler displayHandler;
private IDownloadHandler downloadHandler;
private IKeyboardHandler keyboardHandler;
private ILifeSpanHandler lifeSpanHandler;
@@ -45,6 +46,7 @@ namespace SafeExamBrowser.Browser
public BrowserControl(
IContextMenuHandler contextMenuHandler,
+ IDisplayHandler displayHandler,
IDownloadHandler downloadHandler,
IKeyboardHandler keyboardHandler,
ILifeSpanHandler lifeSpanHandler,
@@ -52,6 +54,7 @@ namespace SafeExamBrowser.Browser
string url) : base(url)
{
this.contextMenuHandler = contextMenuHandler;
+ this.displayHandler = displayHandler;
this.downloadHandler = downloadHandler;
this.keyboardHandler = keyboardHandler;
this.lifeSpanHandler = lifeSpanHandler;
@@ -64,6 +67,7 @@ namespace SafeExamBrowser.Browser
LoadingStateChanged += (o, args) => loadingStateChanged?.Invoke(args.IsLoading);
TitleChanged += (o, args) => titleChanged?.Invoke(args.Title);
+ DisplayHandler = displayHandler;
DownloadHandler = downloadHandler;
KeyboardHandler = keyboardHandler;
LifeSpanHandler = lifeSpanHandler;
diff --git a/SafeExamBrowser.Browser/BrowserIconResource.cs b/SafeExamBrowser.Browser/BrowserIconResource.cs
index 651f057b..ebe15450 100644
--- a/SafeExamBrowser.Browser/BrowserIconResource.cs
+++ b/SafeExamBrowser.Browser/BrowserIconResource.cs
@@ -13,8 +13,13 @@ namespace SafeExamBrowser.Browser
{
public class BrowserIconResource : IIconResource
{
- public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/SafeExamBrowser.ico");
+ public Uri Uri { get; private set; }
public bool IsBitmapResource => true;
public bool IsXamlResource => false;
+
+ public BrowserIconResource(string uri = null)
+ {
+ Uri = new Uri(uri ?? "pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/SafeExamBrowser.ico");
+ }
}
}
diff --git a/SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs b/SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs
new file mode 100644
index 00000000..f361a464
--- /dev/null
+++ b/SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs
@@ -0,0 +1,12 @@
+/*
+ * 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.Browser.Events
+{
+ internal delegate void FaviconChangedEventHandler(string uri);
+}
diff --git a/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs b/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
new file mode 100644
index 00000000..753f411f
--- /dev/null
+++ b/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System.Collections.Generic;
+using System.Linq;
+using CefSharp;
+using CefSharp.Structs;
+using SafeExamBrowser.Browser.Events;
+
+namespace SafeExamBrowser.Browser.Handlers
+{
+ ///
+ /// See https://cefsharp.github.io/api/67.0.0/html/T_CefSharp_IDisplayHandler.htm.
+ ///
+ internal class DisplayHandler : IDisplayHandler
+ {
+ public event FaviconChangedEventHandler FaviconChanged;
+
+ public void OnAddressChanged(IWebBrowser chromiumWebBrowser, AddressChangedEventArgs addressChangedArgs)
+ {
+ }
+
+ public bool OnAutoResize(IWebBrowser chromiumWebBrowser, IBrowser browser, Size newSize)
+ {
+ return false;
+ }
+
+ public bool OnConsoleMessage(IWebBrowser chromiumWebBrowser, ConsoleMessageEventArgs consoleMessageArgs)
+ {
+ return false;
+ }
+
+ public void OnFaviconUrlChange(IWebBrowser chromiumWebBrowser, IBrowser browser, IList urls)
+ {
+ if (urls.Any())
+ {
+ FaviconChanged?.Invoke(urls.First());
+ }
+ }
+
+ public void OnFullscreenModeChange(IWebBrowser chromiumWebBrowser, IBrowser browser, bool fullscreen)
+ {
+ }
+
+ public void OnStatusMessage(IWebBrowser chromiumWebBrowser, StatusMessageEventArgs statusMessageArgs)
+ {
+ }
+
+ public void OnTitleChanged(IWebBrowser chromiumWebBrowser, TitleChangedEventArgs titleChangedArgs)
+ {
+ }
+
+ public bool OnTooltipChanged(IWebBrowser chromiumWebBrowser, ref string text)
+ {
+ return false;
+ }
+ }
+}
diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
index 551b7436..8d509765 100644
--- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
+++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
@@ -66,6 +66,7 @@
+
@@ -74,6 +75,7 @@
Component
+
diff --git a/SafeExamBrowser.Contracts/Core/Events/IconChangedEventHandler.cs b/SafeExamBrowser.Contracts/Core/Events/IconChangedEventHandler.cs
new file mode 100644
index 00000000..e4311c65
--- /dev/null
+++ b/SafeExamBrowser.Contracts/Core/Events/IconChangedEventHandler.cs
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using SafeExamBrowser.Contracts.Configuration;
+
+namespace SafeExamBrowser.Contracts.Core.Events
+{
+ ///
+ /// Event handler used to indicate that the icon of an has changed.
+ ///
+ public delegate void IconChangedEventHandler(IIconResource icon);
+}
diff --git a/SafeExamBrowser.Contracts/Core/Events/InstanceTerminatedEventHandler.cs b/SafeExamBrowser.Contracts/Core/Events/InstanceTerminatedEventHandler.cs
index 6899f664..71bd212a 100644
--- a/SafeExamBrowser.Contracts/Core/Events/InstanceTerminatedEventHandler.cs
+++ b/SafeExamBrowser.Contracts/Core/Events/InstanceTerminatedEventHandler.cs
@@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-
namespace SafeExamBrowser.Contracts.Core.Events
{
///
diff --git a/SafeExamBrowser.Contracts/Core/IApplicationInstance.cs b/SafeExamBrowser.Contracts/Core/IApplicationInstance.cs
index 6ebbc4bb..3e1f676a 100644
--- a/SafeExamBrowser.Contracts/Core/IApplicationInstance.cs
+++ b/SafeExamBrowser.Contracts/Core/IApplicationInstance.cs
@@ -26,6 +26,11 @@ namespace SafeExamBrowser.Contracts.Core
///
string Name { get; }
+ ///
+ /// Event fired when the icon of the application instance has changed.
+ ///
+ event IconChangedEventHandler IconChanged;
+
///
/// Event fired when the application instance has been terminated.
///
diff --git a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
index a1c01d94..0e9831e3 100644
--- a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
+++ b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj
@@ -71,6 +71,7 @@
+
diff --git a/SafeExamBrowser.Contracts/UserInterface/Browser/IBrowserWindow.cs b/SafeExamBrowser.Contracts/UserInterface/Browser/IBrowserWindow.cs
index cea89a39..a155cc2b 100644
--- a/SafeExamBrowser.Contracts/UserInterface/Browser/IBrowserWindow.cs
+++ b/SafeExamBrowser.Contracts/UserInterface/Browser/IBrowserWindow.cs
@@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.UserInterface.Browser.Events;
using SafeExamBrowser.Contracts.UserInterface.Windows;
@@ -46,6 +47,11 @@ namespace SafeExamBrowser.Contracts.UserInterface.Browser
///
void UpdateAddress(string adress);
+ ///
+ /// Updates the icon of the browser window.
+ ///
+ void UpdateIcon(IIconResource icon);
+
///
/// Updates the loading state according to the given value.
///
diff --git a/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs
index 14ed4800..4c3d211e 100644
--- a/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/BrowserWindow.xaml.cs
@@ -9,6 +9,8 @@
using System;
using System.Windows;
using System.Windows.Input;
+using System.Windows.Media.Imaging;
+using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.UserInterface.Browser;
using SafeExamBrowser.Contracts.UserInterface.Browser.Events;
@@ -89,6 +91,11 @@ namespace SafeExamBrowser.UserInterface.Desktop
Dispatcher.Invoke(() => UrlTextBox.Text = url);
}
+ public void UpdateIcon(IIconResource icon)
+ {
+ Dispatcher.BeginInvoke(new Action(() => Icon = new BitmapImage(icon.Uri)));
+ }
+
public void UpdateLoadingState(bool isLoading)
{
Dispatcher.Invoke(() =>
diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationInstanceButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationInstanceButton.xaml.cs
index 125f5a5f..265adf14 100644
--- a/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationInstanceButton.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ApplicationInstanceButton.xaml.cs
@@ -6,10 +6,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+using System;
using System.Windows;
using System.Windows.Controls;
-using SafeExamBrowser.Contracts.Core;
using SafeExamBrowser.Contracts.Configuration;
+using SafeExamBrowser.Contracts.Core;
using SafeExamBrowser.Contracts.UserInterface.Taskbar.Events;
using SafeExamBrowser.UserInterface.Desktop.Utilities;
@@ -37,14 +38,22 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
Text.Text = instance.Name;
Button.ToolTip = instance.Name;
- instance.NameChanged += (name) =>
+ instance.IconChanged += Instance_IconChanged;
+ instance.NameChanged += Instance_NameChanged;
+ }
+
+ private void Instance_IconChanged(IIconResource icon)
+ {
+ Dispatcher.BeginInvoke(new Action(() => Icon.Content = IconResourceLoader.Load(icon)));
+ }
+
+ private void Instance_NameChanged(string name)
+ {
+ Dispatcher.Invoke(() =>
{
- Dispatcher.Invoke(() =>
- {
- Text.Text = name;
- Button.ToolTip = name;
- });
- };
+ Text.Text = name;
+ Button.ToolTip = name;
+ });
}
private void Button_Click(object sender, RoutedEventArgs e)