diff --git a/SafeExamBrowser.Browser/BrowserApplicationController.cs b/SafeExamBrowser.Browser/BrowserApplicationController.cs
index 6613ddca..8d82f504 100644
--- a/SafeExamBrowser.Browser/BrowserApplicationController.cs
+++ b/SafeExamBrowser.Browser/BrowserApplicationController.cs
@@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using CefSharp;
+using SafeExamBrowser.Browser.Handlers;
using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.I18n;
@@ -42,14 +43,7 @@ namespace SafeExamBrowser.Browser
public void Initialize()
{
- var cefSettings = new CefSettings
- {
- CachePath = runtimeInfo.BrowserCachePath,
- LogFile = runtimeInfo.BrowserLogFile,
- // TODO: Set according to current application LogLevel!
- LogSeverity = LogSeverity.Verbose
- };
-
+ var cefSettings = InitializeCefSettings();
var success = Cef.Initialize(cefSettings, true, null);
if (!success)
@@ -86,6 +80,36 @@ namespace SafeExamBrowser.Browser
instance.Window.Show();
}
+ private CefSettings InitializeCefSettings()
+ {
+ var schemeFactory = new SebSchemeHandlerFactory();
+ var cefSettings = new CefSettings
+ {
+ CachePath = runtimeInfo.BrowserCachePath,
+ LogFile = runtimeInfo.BrowserLogFile,
+ // TODO: Set according to current application LogLevel!
+ LogSeverity = LogSeverity.Verbose
+ };
+
+ schemeFactory.ConfigurationDetected += OnConfigurationDetected;
+
+ cefSettings.RegisterScheme(new CefCustomScheme { SchemeName = "seb", SchemeHandlerFactory = schemeFactory });
+ cefSettings.RegisterScheme(new CefCustomScheme { SchemeName = "sebs", SchemeHandlerFactory = schemeFactory });
+
+ return cefSettings;
+ }
+
+ private void OnConfigurationDetected(string url)
+ {
+ // TODO:
+ // 1. Ask whether reconfiguration should be attempted
+ // 2. Contact runtime and ask whether configuration valid and reconfiguration allowed
+ // - If yes, do nothing and wait for shutdown command
+ // - If no, show message box and NAVIGATE TO PREVIOUS PAGE -> but how?
+
+ uiFactory.Show("Detected re-configuration request for " + url, "Info");
+ }
+
private void Button_OnClick(Guid? instanceId = null)
{
if (instanceId.HasValue)
diff --git a/SafeExamBrowser.Browser/Handlers/SebSchemeHandler.cs b/SafeExamBrowser.Browser/Handlers/SebSchemeHandler.cs
new file mode 100644
index 00000000..40627d0d
--- /dev/null
+++ b/SafeExamBrowser.Browser/Handlers/SebSchemeHandler.cs
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018 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.Net;
+using System.Text;
+using System.Threading.Tasks;
+using CefSharp;
+
+namespace SafeExamBrowser.Browser.Handlers
+{
+ internal delegate void ConfigurationDetectedEventHandler(string url);
+
+ ///
+ /// See https://cefsharp.github.io/api/57.0.0/html/T_CefSharp_ResourceHandler.htm.
+ ///
+ internal class SebSchemeHandler : ResourceHandler
+ {
+ internal event ConfigurationDetectedEventHandler ConfigurationDetected;
+
+ public override bool ProcessRequestAsync(IRequest request, ICallback callback)
+ {
+ Task.Run(() =>
+ {
+ using (callback)
+ {
+ var page = "
";
+ var stream = GetMemoryStream(page, Encoding.UTF8);
+
+ ResponseLength = stream.Length;
+ MimeType = "text/html";
+ StatusCode = (int) HttpStatusCode.OK;
+ Stream = stream;
+
+ callback.Continue();
+ ConfigurationDetected?.Invoke(request.Url);
+ }
+ });
+
+ return true;
+ }
+ }
+}
diff --git a/SafeExamBrowser.Browser/Handlers/SebSchemeHandlerFactory.cs b/SafeExamBrowser.Browser/Handlers/SebSchemeHandlerFactory.cs
new file mode 100644
index 00000000..69d952ce
--- /dev/null
+++ b/SafeExamBrowser.Browser/Handlers/SebSchemeHandlerFactory.cs
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018 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 CefSharp;
+
+namespace SafeExamBrowser.Browser.Handlers
+{
+ ///
+ /// See https://cefsharp.github.io/api/57.0.0/html/T_CefSharp_ISchemeHandlerFactory.htm.
+ ///
+ internal class SebSchemeHandlerFactory : ISchemeHandlerFactory
+ {
+ internal event ConfigurationDetectedEventHandler ConfigurationDetected;
+
+ public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
+ {
+ var handler = new SebSchemeHandler();
+
+ handler.ConfigurationDetected += (url) => ConfigurationDetected?.Invoke(url);
+
+ return handler;
+ }
+ }
+}
diff --git a/SafeExamBrowser.Browser/Images/ChromiumLogo.xaml b/SafeExamBrowser.Browser/Images/ChromiumLogo.xaml
deleted file mode 100644
index 2f4b7292..00000000
--- a/SafeExamBrowser.Browser/Images/ChromiumLogo.xaml
+++ /dev/null
@@ -1,200 +0,0 @@
-
-
-
-
-
diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
index 7d5ddbc6..0d9f70cf 100644
--- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
+++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
@@ -66,6 +66,8 @@
+
+
@@ -74,12 +76,6 @@
SafeExamBrowser.Contracts
-
-
- MSBuild:Compile
- Designer
-
-
Designer
diff --git a/SafeExamBrowser.Contracts/Behaviour/IApplicationController.cs b/SafeExamBrowser.Contracts/Behaviour/IApplicationController.cs
index 32240cf1..e8c35df2 100644
--- a/SafeExamBrowser.Contracts/Behaviour/IApplicationController.cs
+++ b/SafeExamBrowser.Contracts/Behaviour/IApplicationController.cs
@@ -10,6 +10,9 @@ using SafeExamBrowser.Contracts.UserInterface.Taskbar;
namespace SafeExamBrowser.Contracts.Behaviour
{
+ ///
+ /// Controls the lifetime and functionality of a (third-party) application which can be accessed via the taskbar.
+ ///
public interface IApplicationController
{
///
@@ -23,7 +26,7 @@ namespace SafeExamBrowser.Contracts.Behaviour
void RegisterApplicationButton(IApplicationButton button);
///
- /// Performs any termination work, e.g. freeing of resources.
+ /// Performs any termination work, e.g. releasing of used resources.
///
void Terminate();
}
diff --git a/SafeExamBrowser.Contracts/UserInterface/IRuntimeWindow.cs b/SafeExamBrowser.Contracts/UserInterface/IRuntimeWindow.cs
index e8e0e8b2..c03ab0b6 100644
--- a/SafeExamBrowser.Contracts/UserInterface/IRuntimeWindow.cs
+++ b/SafeExamBrowser.Contracts/UserInterface/IRuntimeWindow.cs
@@ -12,6 +12,11 @@ namespace SafeExamBrowser.Contracts.UserInterface
{
public interface IRuntimeWindow : ILogObserver, IProgressIndicator, IWindow
{
+ ///
+ /// Determines whether the window will stay on top of other windows.
+ ///
+ bool TopMost { get; set; }
+
///
/// Hides the progress bar.
///
diff --git a/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs b/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs
index 84b3a66c..10ce4e9d 100644
--- a/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs
+++ b/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs
@@ -133,6 +133,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
private void StartSession(bool initial = false)
{
runtimeWindow.Show();
+ runtimeWindow.BringToForeground();
logger.Info(">>>--- Initiating session procedure ---<<<");
if (sessionRunning)
@@ -149,6 +150,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
logger.Info(">>>--- Session is running ---<<<");
runtimeWindow.HideProgressBar();
runtimeWindow.UpdateText(TextKey.RuntimeWindow_ApplicationRunning);
+ runtimeWindow.TopMost = configuration.CurrentSettings.KioskMode != KioskMode.None;
if (configuration.CurrentSettings.KioskMode == KioskMode.DisableExplorerShell)
{
diff --git a/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml b/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml
index f0a98f70..eb03fc2b 100644
--- a/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml
+++ b/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml
@@ -5,7 +5,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Classic"
- mc:Ignorable="d" Title="BrowserWindow" Background="#FFF0F0F0" Height="500" Width="750" WindowState="Maximized" Icon=".\Images\SafeExamBrowser.ico">
+ mc:Ignorable="d" Title="BrowserWindow" Background="#FFF0F0F0" Height="500" Width="750" MinHeight="250" MinWidth="250"
+ WindowState="Maximized" Icon=".\Images\SafeExamBrowser.ico">
@@ -29,7 +30,7 @@
-
+
diff --git a/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml.cs b/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml.cs
index 25816a77..00eaaec4 100644
--- a/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Classic/BrowserWindow.xaml.cs
@@ -88,7 +88,11 @@ namespace SafeExamBrowser.UserInterface.Classic
public void UpdateLoadingState(bool isLoading)
{
- Dispatcher.Invoke(() => LoadingIcon.Visibility = isLoading ? Visibility.Visible : Visibility.Collapsed);
+ Dispatcher.Invoke(() =>
+ {
+ LoadingIcon.Visibility = isLoading ? Visibility.Visible : Visibility.Collapsed;
+ LoadingIcon.Spin = isLoading;
+ });
}
public void UpdateTitle(string title)
@@ -105,7 +109,12 @@ namespace SafeExamBrowser.UserInterface.Classic
Closing += (o, args) => closing?.Invoke();
KeyUp += BrowserWindow_KeyUp;
+ UrlTextBox.GotKeyboardFocus += (o, args) => UrlTextBox.SelectAll();
+ UrlTextBox.GotMouseCapture += UrlTextBox_GotMouseCapture;
+ UrlTextBox.LostKeyboardFocus += (o, args) => UrlTextBox.Tag = null;
+ UrlTextBox.LostFocus += (o, args) => UrlTextBox.Tag = null;
UrlTextBox.KeyUp += UrlTextBox_KeyUp;
+ UrlTextBox.MouseDoubleClick += (o, args) => UrlTextBox.SelectAll();
ReloadButton.Click += (o, args) => ReloadRequested?.Invoke();
BackButton.Click += (o, args) => BackwardNavigationRequested?.Invoke();
ForwardButton.Click += (o, args) => ForwardNavigationRequested?.Invoke();
@@ -114,6 +123,15 @@ namespace SafeExamBrowser.UserInterface.Classic
LoadIcons();
}
+ private void UrlTextBox_GotMouseCapture(object sender, MouseEventArgs e)
+ {
+ if (UrlTextBox.Tag as bool? != true)
+ {
+ UrlTextBox.SelectAll();
+ UrlTextBox.Tag = true;
+ }
+ }
+
private void BrowserWindow_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.F5)
diff --git a/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs b/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs
index b30de8f0..74f4c481 100644
--- a/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs
+++ b/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs
@@ -26,6 +26,12 @@ namespace SafeExamBrowser.UserInterface.Classic
private RuntimeWindowViewModel model;
private WindowClosingEventHandler closing;
+ public bool TopMost
+ {
+ get { return Dispatcher.Invoke(() => Topmost); }
+ set { Dispatcher.Invoke(() => Topmost = value); }
+ }
+
event WindowClosingEventHandler IWindow.Closing
{
add { closing += value; }