SEBWIN-106: Implemented basic favicon handling.

This commit is contained in:
dbuechel 2019-01-17 16:15:10 +01:00
parent 6c3a7bee5c
commit 0ee13c9c8b
13 changed files with 152 additions and 11 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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");
}
}
}

View file

@ -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);
}

View file

@ -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
{
/// <remarks>
/// See https://cefsharp.github.io/api/67.0.0/html/T_CefSharp_IDisplayHandler.htm.
/// </remarks>
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<string> 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;
}
}
}

View file

@ -66,6 +66,7 @@
<Compile Include="BrowserApplicationInfo.cs" />
<Compile Include="BrowserApplicationInstance.cs" />
<Compile Include="BrowserInstanceIdentifier.cs" />
<Compile Include="Events\FaviconChangedEventHandler.cs" />
<Compile Include="Events\PopupRequestedEventArgs.cs" />
<Compile Include="Events\PopupRequestedEventHandler.cs" />
<Compile Include="Events\ReloadRequestedEventHandler.cs" />
@ -74,6 +75,7 @@
<SubType>Component</SubType>
</Compile>
<Compile Include="BrowserIconResource.cs" />
<Compile Include="Handlers\DisplayHandler.cs" />
<Compile Include="Handlers\DownloadHandler.cs" />
<Compile Include="Handlers\KeyboardHandler.cs" />
<Compile Include="Handlers\LifeSpanHandler.cs" />

View file

@ -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
{
/// <summary>
/// Event handler used to indicate that the icon of an <see cref="IApplicationInstance"/> has changed.
/// </summary>
public delegate void IconChangedEventHandler(IIconResource icon);
}

View file

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace SafeExamBrowser.Contracts.Core.Events
{
/// <summary>

View file

@ -26,6 +26,11 @@ namespace SafeExamBrowser.Contracts.Core
/// </summary>
string Name { get; }
/// <summary>
/// Event fired when the icon of the application instance has changed.
/// </summary>
event IconChangedEventHandler IconChanged;
/// <summary>
/// Event fired when the application instance has been terminated.
/// </summary>

View file

@ -71,6 +71,7 @@
<Compile Include="Configuration\DataResources\IResourceSaver.cs" />
<Compile Include="Configuration\SaveStatus.cs" />
<Compile Include="Configuration\Settings\UserInterfaceMode.cs" />
<Compile Include="Core\Events\IconChangedEventHandler.cs" />
<Compile Include="Core\Events\InstanceTerminatedEventHandler.cs" />
<Compile Include="Core\Events\NameChangedEventHandler.cs" />
<Compile Include="Core\IApplicationController.cs" />

View file

@ -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
/// </summary>
void UpdateAddress(string adress);
/// <summary>
/// Updates the icon of the browser window.
/// </summary>
void UpdateIcon(IIconResource icon);
/// <summary>
/// Updates the loading state according to the given value.
/// </summary>

View file

@ -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(() =>

View file

@ -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)