diff --git a/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs
index e1d9df7a..5ca4175c 100644
--- a/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs
+++ b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs
@@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using System;
using SafeExamBrowser.Applications.Contracts;
using SafeExamBrowser.Browser.Contracts.Events;
@@ -38,8 +37,8 @@ namespace SafeExamBrowser.Browser.Contracts
event LoseFocusRequestedEventHandler LoseFocusRequested;
///
- /// Transfers the focus to the browser window.
- /// If true, the first focusable element in the browser window receives focus (passing forward of focus). Otherwise, the last element.
+ /// Transfers the focus to the browser application. If the parameter is true, the first focusable element in the browser window
+ /// receives focus (passing forward of focus). Otherwise, the last element receives focus.
///
void Focus(bool forward);
}
diff --git a/SafeExamBrowser.Browser/BrowserApplication.cs b/SafeExamBrowser.Browser/BrowserApplication.cs
index 9f2504dc..b3eedefc 100644
--- a/SafeExamBrowser.Browser/BrowserApplication.cs
+++ b/SafeExamBrowser.Browser/BrowserApplication.cs
@@ -87,6 +87,14 @@ namespace SafeExamBrowser.Browser
this.windows = new List();
}
+ public void Focus(bool forward)
+ {
+ windows.ForEach(window =>
+ {
+ window.Focus(forward);
+ });
+ }
+
public IEnumerable GetWindows()
{
return new List(windows);
@@ -459,13 +467,5 @@ namespace SafeExamBrowser.Browser
CreateNewWindow();
logger.Info("Successfully reset browser.");
}
-
- public void Focus(bool forward)
- {
- windows.ForEach(window =>
- {
- window.Focus(forward);
- });
- }
}
}
diff --git a/SafeExamBrowser.Browser/BrowserControl.cs b/SafeExamBrowser.Browser/BrowserControl.cs
index 2c9d0879..30ad6721 100644
--- a/SafeExamBrowser.Browser/BrowserControl.cs
+++ b/SafeExamBrowser.Browser/BrowserControl.cs
@@ -72,6 +72,23 @@ namespace SafeExamBrowser.Browser
}
}
+ public async void ExecuteJavascript(string javascript, Action callback)
+ {
+ var result = await control.EvaluateScriptAsync(javascript);
+
+ callback(new JavascriptResult()
+ {
+ Message = result.Message,
+ Result = result.Result,
+ Success = result.Success
+ });
+ }
+
+ public void Find(string term, bool isInitial, bool caseSensitive, bool forward = true)
+ {
+ control.Find(term, forward, caseSensitive, !isInitial);
+ }
+
public void Initialize()
{
control.AddressChanged += (o, e) => AddressChanged?.Invoke(e.Address);
@@ -85,7 +102,7 @@ namespace SafeExamBrowser.Browser
control.FrameLoadStart += Control_FrameLoadStart;
control.IsBrowserInitializedChanged += Control_IsBrowserInitializedChanged;
control.KeyEvent += (w, b, t, k, n, m, s) => keyboardHandler.OnKeyEvent(w, b, t, k, n, m, s);
- control.LoadError += (o, e) => LoadFailed?.Invoke((int) e.ErrorCode, e.ErrorText, e.FailedUrl);
+ control.LoadError += (o, e) => LoadFailed?.Invoke((int) e.ErrorCode, e.ErrorText, e.Frame.IsMain, e.FailedUrl);
control.LoadingProgressChanged += (w, b, p) => displayHandler.OnLoadingProgressChange(w, b, p);
control.LoadingStateChanged += (o, e) => LoadingStateChanged?.Invoke(e.IsLoading);
control.OpenUrlFromTab += (w, b, f, u, t, g, a) => a.Value = requestHandler.OnOpenUrlFromTab(w, b, f, u, t, g);
@@ -94,28 +111,6 @@ namespace SafeExamBrowser.Browser
control.TitleChanged += (o, e) => TitleChanged?.Invoke(e.Title);
}
- private void Control_FrameLoadStart(object sender, FrameLoadStartEventArgs e)
- {
- var browserExamKey = generator.CalculateBrowserExamKeyHash(e.Url);
- var configurationKey = generator.CalculateConfigurationKeyHash(e.Url);
- var api = contentLoader.LoadApi(browserExamKey, configurationKey, appConfig.ProgramBuildVersion);
-
- e.Frame.ExecuteJavaScriptAsync(api);
- }
-
- private void Control_IsBrowserInitializedChanged(object sender, EventArgs e)
- {
- if (control.IsBrowserInitialized)
- {
- control.BrowserCore.GetHost().SetFocus(true);
- }
- }
-
- public void Find(string term, bool isInitial, bool caseSensitive, bool forward = true)
- {
- control.Find(term, forward, caseSensitive, !isInitial);
- }
-
public void NavigateBackwards()
{
control.BrowserCore.GoBack();
@@ -146,18 +141,21 @@ namespace SafeExamBrowser.Browser
control.BrowserCore.SetZoomLevel(level);
}
- ///
- /// Executes the given Javascript code in the browser.
- ///
- public async void ExecuteJavascript(string javascript, Action callback)
+ private void Control_FrameLoadStart(object sender, FrameLoadStartEventArgs e)
{
- var result = await this.control.EvaluateScriptAsync(javascript);
- callback(new JavascriptResult()
+ var browserExamKey = generator.CalculateBrowserExamKeyHash(e.Url);
+ var configurationKey = generator.CalculateConfigurationKeyHash(e.Url);
+ var api = contentLoader.LoadApi(browserExamKey, configurationKey, appConfig.ProgramBuildVersion);
+
+ e.Frame.ExecuteJavaScriptAsync(api);
+ }
+
+ private void Control_IsBrowserInitializedChanged(object sender, EventArgs e)
+ {
+ if (control.IsBrowserInitialized)
{
- Message = result.Message,
- Result = result.Result,
- Success = result.Success
- });
+ control.BrowserCore.GetHost().SetFocus(true);
+ }
}
}
}
diff --git a/SafeExamBrowser.Browser/BrowserWindow.cs b/SafeExamBrowser.Browser/BrowserWindow.cs
index 0cf5c869..33a5ee16 100644
--- a/SafeExamBrowser.Browser/BrowserWindow.cs
+++ b/SafeExamBrowser.Browser/BrowserWindow.cs
@@ -127,6 +127,19 @@ namespace SafeExamBrowser.Browser
Control.Destroy();
}
+ internal void Focus(bool forward)
+ {
+ if (forward)
+ {
+ window.FocusToolbar(forward);
+ }
+ else
+ {
+ window.FocusBrowser();
+ Activate();
+ }
+ }
+
internal void InitializeControl()
{
var cefSharpControl = default(ICefSharpControl);
@@ -159,13 +172,13 @@ namespace SafeExamBrowser.Browser
downloadHandler.DownloadAborted += DownloadHandler_DownloadAborted;
downloadHandler.DownloadUpdated += DownloadHandler_DownloadUpdated;
keyboardHandler.FindRequested += KeyboardHandler_FindRequested;
+ keyboardHandler.FocusAddressBarRequested += KeyboardHandler_FocusAddressBarRequested;
keyboardHandler.HomeNavigationRequested += HomeNavigationRequested;
keyboardHandler.ReloadRequested += ReloadRequested;
+ keyboardHandler.TabPressed += KeyboardHandler_TabPressed;
keyboardHandler.ZoomInRequested += ZoomInRequested;
keyboardHandler.ZoomOutRequested += ZoomOutRequested;
keyboardHandler.ZoomResetRequested += ZoomResetRequested;
- keyboardHandler.TabPressed += TabPressed;
- keyboardHandler.FocusAddressBarRequested += FocusAddressBarRequested;
resourceHandler.SessionIdentifierDetected += (id) => SessionIdentifierDetected?.Invoke(id);
requestHandler.QuitUrlVisited += RequestHandler_QuitUrlVisited;
requestHandler.RequestBlocked += RequestHandler_RequestBlocked;
@@ -267,26 +280,38 @@ namespace SafeExamBrowser.Browser
}
}
- private void Control_LoadFailed(int errorCode, string errorText, string url)
+ private void Control_LoadFailed(int errorCode, string errorText, bool isMainRequest, string url)
{
- if (errorCode == (int) CefErrorCode.None)
+ switch (errorCode)
{
- logger.Info($"Request{(WindowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")} was successful.");
+ case (int) CefErrorCode.Aborted:
+ logger.Info($"Request{(WindowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")} was aborted.");
+ break;
+ case (int) CefErrorCode.InternetDisconnected:
+ logger.Info($"Request{(WindowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")} has failed due to loss of internet connection.");
+ break;
+ case (int) CefErrorCode.None:
+ logger.Info($"Request{(WindowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")} was successful.");
+ break;
+ case (int) CefErrorCode.UnknownUrlScheme:
+ logger.Info($"Request{(WindowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")} has an unknown URL scheme and will be handled by the OS.");
+ break;
+ default:
+ HandleUnknownLoadFailure(errorCode, errorText, isMainRequest, url);
+ break;
}
- else if (errorCode == (int) CefErrorCode.Aborted)
- {
- logger.Info($"Request{(WindowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")} was aborted.");
- }
- else if (errorCode == (int) CefErrorCode.UnknownUrlScheme)
- {
- logger.Info($"Request{(WindowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")} contains unknown URL scheme and will be handled by the OS.");
- }
- else
+ }
+
+ private void HandleUnknownLoadFailure(int errorCode, string errorText, bool isMainRequest, string url)
+ {
+ var requestInfo = $"{errorText} ({errorCode}, {(isMainRequest ? "main" : "resource")} request)";
+
+ logger.Warn($"Request{(WindowSettings.UrlPolicy.CanLogError() ? $" for '{url}'" : "")} failed: {requestInfo}.");
+
+ if (isMainRequest)
{
var title = text.Get(TextKey.Browser_LoadErrorTitle);
- var message = text.Get(TextKey.Browser_LoadErrorMessage).Replace("%%URL%%", WindowSettings.UrlPolicy.CanLogError() ? url : "") + $" {errorText} ({errorCode})";
-
- logger.Warn($"Request{(WindowSettings.UrlPolicy.CanLogError() ? $" for '{url}'" : "")} failed: {errorText} ({errorCode}).");
+ var message = text.Get(TextKey.Browser_LoadErrorMessage).Replace("%%URL%%", WindowSettings.UrlPolicy.CanLogError() ? url : "") + $" {requestInfo}";
Task.Run(() => messageBox.Show(message, title, icon: MessageBoxIcon.Error, parent: window)).ContinueWith(_ => Control.NavigateBackwards());
}
@@ -465,11 +490,32 @@ namespace SafeExamBrowser.Browser
}
}
- private void FocusAddressBarRequested()
+ private void KeyboardHandler_FocusAddressBarRequested()
{
window.FocusAddressBar();
}
+ private void KeyboardHandler_TabPressed(bool shiftPressed)
+ {
+ Control.ExecuteJavascript("document.activeElement.tagName", result =>
+ {
+ var tagName = result.Result as string;
+
+ if (tagName != null && tagName.ToUpper() == "BODY")
+ {
+ // This means the user is now at the start of the focus / tabIndex chain in the website.
+ if (shiftPressed)
+ {
+ window.FocusToolbar(!shiftPressed);
+ }
+ else
+ {
+ LoseFocusRequested?.Invoke(true);
+ }
+ }
+ });
+ }
+
private ChromiumHostControl LifeSpanHandler_CreatePopup()
{
var args = new PopupRequestedEventArgs();
@@ -717,42 +763,6 @@ namespace SafeExamBrowser.Browser
}
}
- private void TabPressed(bool shiftPressed)
- {
- Control.ExecuteJavascript("document.activeElement.tagName", result =>
- {
- var tagName = result.Result as string;
- if (tagName != null)
- {
- if (tagName.ToUpper() == "BODY")
- {
- // this means the user is now at the start of the focus / tabIndex chain in the website
- if (shiftPressed)
- {
- window.FocusToolbar(!shiftPressed);
- }
- else
- {
- LoseFocusRequested?.Invoke(true);
- }
- }
- }
- });
- }
-
- internal void Focus(bool forward)
- {
- if (forward)
- {
- window.FocusToolbar(forward);
- }
- else
- {
- window.FocusBrowser();
- Activate();
- }
- }
-
private double CalculateZoomPercentage()
{
return (zoomLevel * 25.0) + 100.0;
diff --git a/SafeExamBrowser.UserInterface.Contracts/Browser/Events/LoadFailedEventHandler.cs b/SafeExamBrowser.UserInterface.Contracts/Browser/Events/LoadFailedEventHandler.cs
index 6e490de4..c99e2c4a 100644
--- a/SafeExamBrowser.UserInterface.Contracts/Browser/Events/LoadFailedEventHandler.cs
+++ b/SafeExamBrowser.UserInterface.Contracts/Browser/Events/LoadFailedEventHandler.cs
@@ -11,5 +11,5 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser.Events
///
/// Indicates a load error for a browser request.
///
- public delegate void LoadFailedEventHandler(int errorCode, string errorText, string url);
+ public delegate void LoadFailedEventHandler(int errorCode, string errorText, bool isMainRequest, string url);
}
diff --git a/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserControl.cs b/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserControl.cs
index a27c5c8e..c70a9125 100644
--- a/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserControl.cs
+++ b/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserControl.cs
@@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+using System;
using SafeExamBrowser.UserInterface.Contracts.Browser.Data;
using SafeExamBrowser.UserInterface.Contracts.Browser.Events;
@@ -63,9 +64,9 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
void Destroy();
///
- /// Executes the given Javascript code in the browser.
+ /// Executes the given JavaScript code in the browser.
///
- void ExecuteJavascript(string javascript, System.Action callback);
+ void ExecuteJavascript(string code, Action callback);
///
/// Attempts to find the given term on the current page according to the specified parameters.
diff --git a/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserWindow.cs b/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserWindow.cs
index b41cc25d..f126b0a4 100644
--- a/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserWindow.cs
+++ b/SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserWindow.cs
@@ -29,7 +29,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
/// Enables the forward navigation button.
///
bool CanNavigateForwards { set; }
-
+
///
/// The native handle of the window.
///
@@ -90,6 +90,22 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
///
event ActionRequestedEventHandler ZoomResetRequested;
+ ///
+ /// Sets the focus on the address bar of the window.
+ ///
+ void FocusAddressBar();
+
+ ///
+ /// Sets the focus on the browser content of the window.
+ ///
+ void FocusBrowser();
+
+ ///
+ /// Sets the focus on the toolbar of the window. If the parameter is set to true, the first focusable control on the toolbar gets focused.
+ /// If it is set to false, the last one.
+ ///
+ void FocusToolbar(bool forward);
+
///
/// Displays the find toolbar to search the content of a page.
///
@@ -129,18 +145,5 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
/// Updates the display value of the current page zoom. Value is expected to be in percentage.
///
void UpdateZoomLevel(double value);
-
- ///
- /// Sets the focus to the toolbar.
- ///
- /// If true, the first focusable control on the toolbar gets focused. If false, the last one.
- void FocusToolbar(bool forward);
-
- ///
- /// Sets the focus to the browser.
- ///
- void FocusBrowser();
-
- void FocusAddressBar();
}
}