diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
index 78d4791..14c4732 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.md
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -1,17 +1,18 @@
---
name: Bug Report
-about: Create a bug report to help us improve Safe Exam Browser.
+about: Create a bug report to help us improve the Safe Exam Browser Patch
title: ''
-labels: ''
-assignees: dbuechel
+labels: bug
+assignees: usefulstuffs
---
> [!IMPORTANT]
-> - Please _always_ consult the documentation first before creating a bug report: https://safeexambrowser.org/windows/win_usermanual_en.html.
+> - Please _always_ consult the FAQs before creating an issue: https://github.com/school-cheating/SEBPatch/wiki/FAQs.
> - Please _always_ attach the log file(s) of the affected session(s)! They can be found under `%LocalAppData%\SafeExamBrowser\Logs`.
+> - Please follow this issue template. Saves me some work while reading all issues.
-**Describe the Bug**
+**Bug Description**
A clear and concise description of what the bug is.
**Steps to Reproduce**
@@ -29,7 +30,18 @@ If applicable, add screenshots to help explain your problem.
**Version Information**
- OS: [e.g. Windows 10 Professional, Version 1803]
- - SEB-Version [e.g. SEB 3.0.1]
+ - SEB version: [e.g. SEB 3.0.1]
+ - SEB patch version: [e.g. 1.5.1]
**Additional Context**
Add any other context about the problem here.
+
+**SEB Logs**
+```
+Paste here the SEB logs
+```
+
+**SEB Patcher logs (optional, read below)**
+```
+Paste here the SEB patcher logs (if issue is SEB patcher related, else just ignore this section)
+```
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 722ea42..234bbe6 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,11 @@
blank_issues_enabled: false
contact_links:
- - name: Wiki
- url: https://github.com/school-cheating/SEBPatch/wiki
- about: Before opening an issue, check out the wiki to see if your issue is listed there.
+ - name: FAQs
+ url: https://github.com/school-cheating/SEBPatch/wiki/FAQs
+ about: Before opening an issue, check out the FAQs. Any issue corresponding to the FAQs will be ignored and closed.
+ - name: Questions
+ url: https://github.com/school-cheating/SEBPatch/discussions/categories/q-a
+ about: Ask questions here about the Safe Exam Browser Patch
+ - name: Feature Requests
+ url: https://github.com/school-cheating/SEBPatch/discussions/categories/ideas
+ about: Propose a feature or a change for the Safe Exam Browser Patch.
diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md
deleted file mode 100644
index 325de6b..0000000
--- a/.github/ISSUE_TEMPLATE/feature-request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature Request
-about: Suggest an idea or new feature for Safe Exam Browser.
-title: ''
-labels: ''
-assignees: dbuechel
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/README.md b/README.md
index 34892dd..1d04a4a 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
# Safe Exam Browser Patch
A patch to bypass Safe Exam Browser restrictions.
-- Patch for version 3.8.0.742 has been deprecated and will not receive updates in the future, please upgrade to Safe Exam Browser 3.9.0.787.
+- Currently supported SEB version: 3.9.0.787
-## How to use
-Check out the [Wiki](https://github.com/school-cheating/SEBPatch/wiki)
+## [HOW TO INSTALL](https://github.com/school-cheating/SEBPatch/wiki/Instructions)
+I put this bigger so you actually read it and stop asking how to install the patch.
## Mirrors
In case you can't download from the latest release, here is a list of mirrors (will be updated eventually):
diff --git a/SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs
index a68529e..dba759b 100644
--- a/SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs
+++ b/SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs
index 080133c..8f82ebe 100644
--- a/SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs
+++ b/SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs
index b399c7e..dc2e00b 100644
--- a/SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs
+++ b/SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.Contracts/FactoryResult.cs b/SafeExamBrowser.Applications.Contracts/FactoryResult.cs
index cb0a7bd..0286fe7 100644
--- a/SafeExamBrowser.Applications.Contracts/FactoryResult.cs
+++ b/SafeExamBrowser.Applications.Contracts/FactoryResult.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.Contracts/IApplication.cs b/SafeExamBrowser.Applications.Contracts/IApplication.cs
index 249b878..27b4a13 100644
--- a/SafeExamBrowser.Applications.Contracts/IApplication.cs
+++ b/SafeExamBrowser.Applications.Contracts/IApplication.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs b/SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs
index 8b30fb5..c2d0145 100644
--- a/SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs
+++ b/SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs b/SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs
index 7981578..2daf8c8 100644
--- a/SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs
+++ b/SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs
index 48034c2..dbc52c2 100644
--- a/SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs
+++ b/SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs
@@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Safe Exam Browser")]
[assembly: AssemblyCompany("ETH Zürich")]
[assembly: AssemblyProduct("SafeExamBrowser.Applications.Contracts")]
-[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")]
+[assembly: AssemblyCopyright("Copyright © 2025 ETH Zürich, IT Services")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
diff --git a/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs b/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs
index 074e1cb..8889703 100644
--- a/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs
+++ b/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs
index 61b13c3..de49e2e 100644
--- a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs
+++ b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs
index f5c9935..80a3a0d 100644
--- a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs
+++ b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs
index cf06347..4075e42 100644
--- a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs
+++ b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs
index 5a24166..f7b4cdf 100644
--- a/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs
+++ b/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs
@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Safe Exam Browser")]
[assembly: AssemblyCompany("ETH Zürich")]
[assembly: AssemblyProduct("SafeExamBrowser.Applications.UnitTests")]
-[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")]
+[assembly: AssemblyCopyright("Copyright © 2025 ETH Zürich, IT Services")]
[assembly: ComVisible(false)]
diff --git a/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj b/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj
index a6b7500..466b469 100644
--- a/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj
+++ b/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj
@@ -1,8 +1,9 @@
-
-
-
+
+
+
+
Debug
@@ -68,72 +69,72 @@
..\packages\Microsoft.ApplicationInsights.2.22.0\lib\net46\Microsoft.ApplicationInsights.dll
-
- ..\packages\Microsoft.Testing.Extensions.Telemetry.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.Telemetry.dll
+
+ ..\packages\Microsoft.Testing.Platform.MSBuild.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.MSBuild.dll
-
- ..\packages\Microsoft.Testing.Extensions.TrxReport.Abstractions.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.TrxReport.Abstractions.dll
+
+ ..\packages\Microsoft.Testing.Extensions.Telemetry.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.Telemetry.dll
-
- ..\packages\Microsoft.Testing.Extensions.VSTestBridge.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.VSTestBridge.dll
+
+ ..\packages\Microsoft.Testing.Extensions.TrxReport.Abstractions.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.TrxReport.Abstractions.dll
-
- ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.2\lib\netstandard2.0\Microsoft.Testing.Platform.dll
+
+ ..\packages\Microsoft.Testing.Extensions.VSTestBridge.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.VSTestBridge.dll
-
- ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.2\lib\netstandard2.0\Microsoft.Testing.Platform.MSBuild.dll
+
+ ..\packages\Microsoft.Testing.Platform.1.5.2\lib\netstandard2.0\Microsoft.Testing.Platform.dll
- ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll
+ ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll
- ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll
+ ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll
- ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll
+ ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll
- ..\packages\MSTest.TestFramework.3.2.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
+ ..\packages\MSTest.TestFramework.3.7.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
- ..\packages\MSTest.TestFramework.3.2.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
+ ..\packages\MSTest.TestFramework.3.7.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
-
- ..\packages\Moq.4.20.70\lib\net462\Moq.dll
+
+ ..\packages\Moq.4.20.72\lib\net462\Moq.dll
-
- ..\packages\NuGet.Frameworks.6.9.1\lib\net472\NuGet.Frameworks.dll
+
+ ..\packages\NuGet.Frameworks.6.12.1\lib\net472\NuGet.Frameworks.dll
-
- ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+ ..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll
-
- ..\packages\System.Collections.Immutable.8.0.0\lib\net462\System.Collections.Immutable.dll
+
+ ..\packages\System.Collections.Immutable.9.0.1\lib\net462\System.Collections.Immutable.dll
-
- ..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll
+
+ ..\packages\System.Diagnostics.DiagnosticSource.9.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll
-
- ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
+
+ ..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll
-
- ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+ ..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll
-
- ..\packages\System.Reflection.Metadata.8.0.0\lib\net462\System.Reflection.Metadata.dll
+
+ ..\packages\System.Reflection.Metadata.9.0.1\lib\net462\System.Reflection.Metadata.dll
-
- ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll
-
- ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+ ..\packages\System.Threading.Tasks.Extensions.4.6.0\lib\net462\System.Threading.Tasks.Extensions.dll
@@ -182,18 +183,26 @@
SafeExamBrowser.WindowsApi.Contracts
+
+
+
+
+
+
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
\ No newline at end of file
diff --git a/SafeExamBrowser.Applications.UnitTests/app.config b/SafeExamBrowser.Applications.UnitTests/app.config
index 9821a52..4a41c0d 100644
--- a/SafeExamBrowser.Applications.UnitTests/app.config
+++ b/SafeExamBrowser.Applications.UnitTests/app.config
@@ -4,7 +4,7 @@
-
+
@@ -12,7 +12,7 @@
-
+
@@ -20,15 +20,23 @@
-
+
-
+
-
+
+
+
+
+
+
+
+
+
diff --git a/SafeExamBrowser.Applications.UnitTests/packages.config b/SafeExamBrowser.Applications.UnitTests/packages.config
index f170b50..da1800f 100644
--- a/SafeExamBrowser.Applications.UnitTests/packages.config
+++ b/SafeExamBrowser.Applications.UnitTests/packages.config
@@ -2,22 +2,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SafeExamBrowser.Applications/ApplicationFactory.cs b/SafeExamBrowser.Applications/ApplicationFactory.cs
index 44be9f7..497600d 100644
--- a/SafeExamBrowser.Applications/ApplicationFactory.cs
+++ b/SafeExamBrowser.Applications/ApplicationFactory.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs b/SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs
index 564a038..cf61b3a 100644
--- a/SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs
+++ b/SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications/ExternalApplication.cs b/SafeExamBrowser.Applications/ExternalApplication.cs
index 1767dc1..51371d7 100644
--- a/SafeExamBrowser.Applications/ExternalApplication.cs
+++ b/SafeExamBrowser.Applications/ExternalApplication.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications/ExternalApplicationInstance.cs b/SafeExamBrowser.Applications/ExternalApplicationInstance.cs
index 36e8f6c..fd4ccbf 100644
--- a/SafeExamBrowser.Applications/ExternalApplicationInstance.cs
+++ b/SafeExamBrowser.Applications/ExternalApplicationInstance.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications/ExternalApplicationWindow.cs b/SafeExamBrowser.Applications/ExternalApplicationWindow.cs
index fd07e07..ebdf752 100644
--- a/SafeExamBrowser.Applications/ExternalApplicationWindow.cs
+++ b/SafeExamBrowser.Applications/ExternalApplicationWindow.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs
index 615967b..7389252 100644
--- a/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs
+++ b/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Safe Exam Browser")]
[assembly: AssemblyCompany("ETH Zürich")]
[assembly: AssemblyProduct("SafeExamBrowser.Applications")]
-[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")]
+[assembly: AssemblyCopyright("Copyright © 2025 ETH Zürich, IT Services")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
diff --git a/SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs b/SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs
index 86c5a22..39773d3 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs
+++ b/SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs b/SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs
index 6bc0fc8..a444e47 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs
+++ b/SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs
index 73b80cb..5b7e8b4 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs
+++ b/SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs
index c3ab885..3f40173 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs
+++ b/SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs
index 4e9a13a..c60f7d9 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs
+++ b/SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs
index b31dce0..6590a2a 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs
+++ b/SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs
index b256954..62dda56 100644
--- a/SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs
+++ b/SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs
index 963e38a..65b3a19 100644
--- a/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs
+++ b/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs
index b0f571f..9e1fed3 100644
--- a/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs
+++ b/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs
index 97ff254..863abf8 100644
--- a/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs
+++ b/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Filters/Request.cs b/SafeExamBrowser.Browser.Contracts/Filters/Request.cs
index 81a39fe..1adbba6 100644
--- a/SafeExamBrowser.Browser.Contracts/Filters/Request.cs
+++ b/SafeExamBrowser.Browser.Contracts/Filters/Request.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs
index 7d0bba7..3c7bacc 100644
--- a/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs
+++ b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs b/SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs
index 6cc3af1..09affa1 100644
--- a/SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs
+++ b/SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs b/SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs
index 0dfc261..f6a812c 100644
--- a/SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs
+++ b/SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs
@@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Safe Exam Browser")]
[assembly: AssemblyCompany("ETH Zürich")]
[assembly: AssemblyProduct("SafeExamBrowser.Browser.Contracts")]
-[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")]
+[assembly: AssemblyCopyright("Copyright © 2025 ETH Zürich, IT Services")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs b/SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs
index 1bd2604..6eaa215 100644
--- a/SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* This Source Code Form is subject to the terms of the Mozilla internal
* License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs
index 195b64f..941c5b5 100644
--- a/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs
index f1ec7b0..85c3b33 100644
--- a/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs
index 6ba74bd..d4af886 100644
--- a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs
index 6ee35eb..4d49b26 100644
--- a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs
index 153677a..22e0815 100644
--- a/SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs
index 887bc4f..b2e8dac 100644
--- a/SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -80,7 +80,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
threadId = Thread.CurrentThread.ManagedThreadId;
};
- var status = sut.OnFileDialog(default, default, mode, title, initialPath, default, callback.Object);
+ var status = sut.OnFileDialog(default, default, mode, title, initialPath, default, default, default, callback.Object);
sync.WaitOne();
diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs
index 1ae483f..e525c9d 100644
--- a/SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs
index 7fe625a..822a30e 100644
--- a/SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -108,7 +108,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
};
sut.DownloadUpdated += (state) => failed = true;
- sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
+ sut.OnBeforeDownload(default, default, item, callback.Object);
sync.WaitOne();
callback.VerifyNoOtherCalls();
@@ -145,7 +145,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
sut.ConfigurationDownloadRequested += (f, a) => failed = true;
sut.DownloadUpdated += (state) => failed = true;
- sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
+ sut.OnBeforeDownload(default, default, item, callback.Object);
sync.WaitOne();
callback.Verify(c => c.Continue(It.Is(p => p.Equals(downloadPath)), false), Times.Once);
@@ -180,7 +180,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
sut.ConfigurationDownloadRequested += (f, a) => failed = true;
sut.DownloadUpdated += (state) => failed = true;
- sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
+ sut.OnBeforeDownload(default, default, item, callback.Object);
sync.WaitOne();
var downloadPath = Path.Combine(Environment.ExpandEnvironmentVariables(settings.DownAndUploadDirectory), item.SuggestedFileName);
@@ -202,12 +202,13 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
Url = "https://somehost.org/somefile.abc"
};
+ appConfig.ConfigurationFileMimeType = "application/seb";
settings.AllowDownloads = false;
settings.AllowConfigurationDownloads = false;
sut.ConfigurationDownloadRequested += (file, args) => fail = true;
sut.DownloadUpdated += (state) => fail = true;
- sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
+ sut.OnBeforeDownload(default, default, item, callback.Object);
callback.VerifyNoOtherCalls();
Assert.IsFalse(fail);
@@ -233,7 +234,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
settings.AllowConfigurationDownloads = false;
sut.ConfigurationDownloadRequested += (f, a) => failed = true;
- sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
+ sut.OnBeforeDownload(default, default, item, callback.Object);
sync.WaitOne();
Assert.IsFalse(failed);
@@ -246,7 +247,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
};
item.PercentComplete = 10;
- sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback));
+ sut.OnDownloadUpdated(default, default, item, default);
sync.WaitOne();
Assert.IsFalse(state.IsCancelled);
@@ -255,7 +256,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId);
item.PercentComplete = 20;
- sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback));
+ sut.OnDownloadUpdated(default, default, item, default);
sync.WaitOne();
Assert.IsFalse(state.IsCancelled);
@@ -265,7 +266,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
item.PercentComplete = 50;
item.IsCancelled = true;
- sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback));
+ sut.OnDownloadUpdated(default, default, item, default);
sync.WaitOne();
Assert.IsFalse(failed);
@@ -297,7 +298,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
};
sut.DownloadUpdated += (state) => failed = true;
- sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object);
+ sut.OnBeforeDownload(default, default, item, callback.Object);
sync.WaitOne();
callback.Verify(c => c.Continue(It.Is(p => p.Equals(args.DownloadPath)), false), Times.Once);
diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs
index 355bc4b..fd5a89a 100644
--- a/SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs
index db7954a..64c554f 100644
--- a/SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs
index 7270cf6..92b3111 100644
--- a/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser.UnitTests/Properties/AssemblyInfo.cs b/SafeExamBrowser.Browser.UnitTests/Properties/AssemblyInfo.cs
index a3c17ac..29e305f 100644
--- a/SafeExamBrowser.Browser.UnitTests/Properties/AssemblyInfo.cs
+++ b/SafeExamBrowser.Browser.UnitTests/Properties/AssemblyInfo.cs
@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Safe Exam Browser")]
[assembly: AssemblyCompany("ETH Zürich")]
[assembly: AssemblyProduct("SafeExamBrowser.Browser.UnitTests")]
-[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")]
+[assembly: AssemblyCopyright("Copyright © 2025 ETH Zürich, IT Services")]
[assembly: ComVisible(false)]
diff --git a/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj b/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj
index 9a48f2a..df98d1c 100644
--- a/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj
+++ b/SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj
@@ -1,11 +1,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
Debug
@@ -67,82 +68,82 @@
..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll
-
- ..\packages\CefSharp.Common.121.3.130\lib\net462\CefSharp.dll
+
+ ..\packages\CefSharp.Common.131.3.50\lib\net462\CefSharp.dll
-
- ..\packages\CefSharp.Common.121.3.130\lib\net462\CefSharp.Core.dll
+
+ ..\packages\CefSharp.Common.131.3.50\lib\net462\CefSharp.Core.dll
..\packages\Microsoft.ApplicationInsights.2.22.0\lib\net46\Microsoft.ApplicationInsights.dll
-
- ..\packages\Microsoft.Testing.Extensions.Telemetry.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.Telemetry.dll
+
+ ..\packages\Microsoft.Testing.Platform.MSBuild.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.MSBuild.dll
-
- ..\packages\Microsoft.Testing.Extensions.TrxReport.Abstractions.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.TrxReport.Abstractions.dll
+
+ ..\packages\Microsoft.Testing.Extensions.Telemetry.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.Telemetry.dll
-
- ..\packages\Microsoft.Testing.Extensions.VSTestBridge.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.VSTestBridge.dll
+
+ ..\packages\Microsoft.Testing.Extensions.TrxReport.Abstractions.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.TrxReport.Abstractions.dll
-
- ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.2\lib\netstandard2.0\Microsoft.Testing.Platform.dll
+
+ ..\packages\Microsoft.Testing.Extensions.VSTestBridge.1.5.2\lib\netstandard2.0\Microsoft.Testing.Extensions.VSTestBridge.dll
-
- ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.2\lib\netstandard2.0\Microsoft.Testing.Platform.MSBuild.dll
+
+ ..\packages\Microsoft.Testing.Platform.1.5.2\lib\netstandard2.0\Microsoft.Testing.Platform.dll
- ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll
+ ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll
- ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll
+ ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll
- ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll
+ ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll
- ..\packages\MSTest.TestFramework.3.2.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
+ ..\packages\MSTest.TestFramework.3.7.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
- ..\packages\MSTest.TestFramework.3.2.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
+ ..\packages\MSTest.TestFramework.3.7.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
-
- ..\packages\Moq.4.20.70\lib\net462\Moq.dll
+
+ ..\packages\Moq.4.20.72\lib\net462\Moq.dll
-
- ..\packages\NuGet.Frameworks.6.9.1\lib\net472\NuGet.Frameworks.dll
+
+ ..\packages\NuGet.Frameworks.6.12.1\lib\net472\NuGet.Frameworks.dll
-
- ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+ ..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll
-
- ..\packages\System.Collections.Immutable.8.0.0\lib\net462\System.Collections.Immutable.dll
+
+ ..\packages\System.Collections.Immutable.9.0.1\lib\net462\System.Collections.Immutable.dll
-
- ..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll
+
+ ..\packages\System.Diagnostics.DiagnosticSource.9.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll
-
- ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
+
+ ..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll
-
- ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+ ..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll
-
- ..\packages\System.Reflection.Metadata.8.0.0\lib\net462\System.Reflection.Metadata.dll
+
+ ..\packages\System.Reflection.Metadata.9.0.1\lib\net462\System.Reflection.Metadata.dll
-
- ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll
-
- ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+ ..\packages\System.Threading.Tasks.Extensions.4.6.0\lib\net462\System.Threading.Tasks.Extensions.dll
@@ -198,23 +199,31 @@
SafeExamBrowser.UserInterface.Contracts
+
+
+
+
+
+
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/SafeExamBrowser.Browser.UnitTests/app.config b/SafeExamBrowser.Browser.UnitTests/app.config
index bbe04ab..ee510e7 100644
--- a/SafeExamBrowser.Browser.UnitTests/app.config
+++ b/SafeExamBrowser.Browser.UnitTests/app.config
@@ -4,11 +4,11 @@
-
+
-
+
@@ -16,11 +16,11 @@
-
+
-
+
@@ -28,7 +28,7 @@
-
+
@@ -36,15 +36,19 @@
-
+
-
+
-
+
+
+
+
+
diff --git a/SafeExamBrowser.Browser.UnitTests/packages.config b/SafeExamBrowser.Browser.UnitTests/packages.config
index dbfb0a9..da5a1d8 100644
--- a/SafeExamBrowser.Browser.UnitTests/packages.config
+++ b/SafeExamBrowser.Browser.UnitTests/packages.config
@@ -1,26 +1,27 @@
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SafeExamBrowser.Browser/BrowserApplication.cs b/SafeExamBrowser.Browser/BrowserApplication.cs
index f11248d..b27ed63 100644
--- a/SafeExamBrowser.Browser/BrowserApplication.cs
+++ b/SafeExamBrowser.Browser/BrowserApplication.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -116,18 +116,10 @@ namespace SafeExamBrowser.Browser
if (success)
{
+ InitializeCookies();
+ InitializeDownAndUploadDirectory();
InitializeIntegrityKeys();
- if (settings.DeleteCookiesOnStartup)
- {
- DeleteCookies();
- }
-
- if (settings.UseTemporaryDownAndUploadDirectory)
- {
- CreateTemporaryDownAndUploadDirectory();
- }
-
logger.Info("Initialized browser.");
}
else
@@ -144,36 +136,23 @@ namespace SafeExamBrowser.Browser
public void Terminate()
{
logger.Info("Initiating termination...");
+
AwaitReady();
foreach (var window in windows)
{
window.Closed -= Window_Closed;
window.Close();
+
logger.Info($"Closed browser window #{window.Id}.");
}
- if (settings.UseTemporaryDownAndUploadDirectory)
- {
- DeleteTemporaryDownAndUploadDirectory();
- }
-
- if (settings.DeleteCookiesOnShutdown)
- {
- DeleteCookies();
- }
-
+ FinalizeCookies();
+ FinalizeDownAndUploadDirectory();
Cef.Shutdown();
- logger.Info("Terminated browser.");
+ FinalizeCache();
- if (settings.DeleteCacheOnShutdown && settings.DeleteCookiesOnShutdown)
- {
- DeleteCache();
- }
- else
- {
- logger.Info("Retained browser cache.");
- }
+ logger.Info("Terminated browser.");
}
private void AwaitReady()
@@ -231,46 +210,6 @@ namespace SafeExamBrowser.Browser
WindowsChanged?.Invoke();
}
- private void CreateTemporaryDownAndUploadDirectory()
- {
- try
- {
- settings.DownAndUploadDirectory = Path.Combine(appConfig.TemporaryDirectory, Path.GetRandomFileName());
- Directory.CreateDirectory(settings.DownAndUploadDirectory);
- logger.Info($"Created temporary down- and upload directory.");
- }
- catch (Exception e)
- {
- logger.Error("Failed to create temporary down- and upload directory!", e);
- }
- }
-
- private void DeleteTemporaryDownAndUploadDirectory()
- {
- try
- {
- Directory.Delete(settings.DownAndUploadDirectory, true);
- logger.Info("Deleted temporary down- and upload directory.");
- }
- catch (Exception e)
- {
- logger.Error("Failed to delete temporary down- and upload directory!", e);
- }
- }
-
- private void DeleteCache()
- {
- try
- {
- Directory.Delete(appConfig.BrowserCachePath, true);
- logger.Info("Deleted browser cache.");
- }
- catch (Exception e)
- {
- logger.Error("Failed to delete browser cache!", e);
- }
- }
-
private void DeleteCookies()
{
var callback = new TaskDeleteCookiesCallback();
@@ -297,6 +236,50 @@ namespace SafeExamBrowser.Browser
}
}
+ private void FinalizeCache()
+ {
+ if (settings.DeleteCacheOnShutdown && settings.DeleteCookiesOnShutdown)
+ {
+ try
+ {
+ Directory.Delete(appConfig.BrowserCachePath, true);
+ logger.Info("Deleted browser cache.");
+ }
+ catch (Exception e)
+ {
+ logger.Error("Failed to delete browser cache!", e);
+ }
+ }
+ else
+ {
+ logger.Info("Retained browser cache.");
+ }
+ }
+
+ private void FinalizeCookies()
+ {
+ if (settings.DeleteCookiesOnShutdown)
+ {
+ DeleteCookies();
+ }
+ }
+
+ private void FinalizeDownAndUploadDirectory()
+ {
+ if (settings.UseTemporaryDownAndUploadDirectory)
+ {
+ try
+ {
+ Directory.Delete(settings.DownAndUploadDirectory, true);
+ logger.Info("Deleted temporary down- and upload directory.");
+ }
+ catch (Exception e)
+ {
+ logger.Error("Failed to delete temporary down- and upload directory!", e);
+ }
+ }
+ }
+
private string GenerateStartUrl()
{
var url = settings.StartUrl;
@@ -371,6 +354,53 @@ namespace SafeExamBrowser.Browser
return cefSettings;
}
+ private void InitializeCookies()
+ {
+ if (settings.DeleteCookiesOnStartup)
+ {
+ DeleteCookies();
+ }
+ }
+
+ private void InitializeDownAndUploadDirectory()
+ {
+ if (settings.UseTemporaryDownAndUploadDirectory)
+ {
+ InitializeTemporaryDownAndUploadDirectory();
+ }
+ else if (!string.IsNullOrEmpty(settings.DownAndUploadDirectory))
+ {
+ InitializeCustomDownAndUploadDirectory();
+ }
+ }
+
+ private void InitializeCustomDownAndUploadDirectory()
+ {
+ if (!Directory.Exists(Environment.ExpandEnvironmentVariables(settings.DownAndUploadDirectory)))
+ {
+ logger.Warn("The configured down- and upload directory does not exist! Falling back to the default directory...");
+ settings.DownAndUploadDirectory = default;
+ }
+ else
+ {
+ logger.Debug("Using custom down- and upload directory as defined in the active configuration.");
+ }
+ }
+
+ private void InitializeTemporaryDownAndUploadDirectory()
+ {
+ try
+ {
+ settings.DownAndUploadDirectory = Path.Combine(appConfig.TemporaryDirectory, Path.GetRandomFileName());
+ Directory.CreateDirectory(settings.DownAndUploadDirectory);
+ logger.Info($"Created temporary down- and upload directory.");
+ }
+ catch (Exception e)
+ {
+ logger.Error("Failed to create temporary down- and upload directory!", e);
+ }
+ }
+
private void InitializeIntegrityKeys()
{
logger.Debug($"Browser Exam Key (BEK) transmission is {(settings.SendBrowserExamKey ? "enabled" : "disabled")}.");
diff --git a/SafeExamBrowser.Browser/BrowserControl.cs b/SafeExamBrowser.Browser/BrowserControl.cs
index 64a14b1..445d4b0 100644
--- a/SafeExamBrowser.Browser/BrowserControl.cs
+++ b/SafeExamBrowser.Browser/BrowserControl.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -26,6 +26,9 @@ namespace SafeExamBrowser.Browser
private readonly IDialogHandler dialogHandler;
private readonly IDisplayHandler displayHandler;
private readonly IDownloadHandler downloadHandler;
+ private readonly IDragHandler dragHandler;
+ private readonly IFocusHandler focusHandler;
+ private readonly IJsDialogHandler javaScriptDialogHandler;
private readonly IKeyboardHandler keyboardHandler;
private readonly ILogger logger;
private readonly IRenderProcessMessageHandler renderProcessMessageHandler;
@@ -47,6 +50,9 @@ namespace SafeExamBrowser.Browser
IDialogHandler dialogHandler,
IDisplayHandler displayHandler,
IDownloadHandler downloadHandler,
+ IDragHandler dragHandler,
+ IFocusHandler focusHandler,
+ IJsDialogHandler javaScriptDialogHandler,
IKeyboardHandler keyboardHandler,
ILogger logger,
IRenderProcessMessageHandler renderProcessMessageHandler,
@@ -57,6 +63,9 @@ namespace SafeExamBrowser.Browser
this.dialogHandler = dialogHandler;
this.displayHandler = displayHandler;
this.downloadHandler = downloadHandler;
+ this.dragHandler = dragHandler;
+ this.focusHandler = focusHandler;
+ this.javaScriptDialogHandler = javaScriptDialogHandler;
this.keyboardHandler = keyboardHandler;
this.logger = logger;
this.renderProcessMessageHandler = renderProcessMessageHandler;
@@ -67,6 +76,7 @@ namespace SafeExamBrowser.Browser
{
if (!control.IsDisposed)
{
+ control.CloseDevTools();
control.Dispose(true);
}
}
@@ -119,22 +129,31 @@ namespace SafeExamBrowser.Browser
control.AddressChanged += (o, e) => AddressChanged?.Invoke(e.Address);
control.AuthCredentialsRequired += (w, b, o, i, h, p, r, s, c, a) => a.Value = requestHandler.GetAuthCredentials(w, b, o, i, h, p, r, s, c);
control.BeforeBrowse += (w, b, f, r, u, i, a) => a.Value = requestHandler.OnBeforeBrowse(w, b, f, r, u, i);
- control.BeforeDownload += (w, b, d, c) => downloadHandler.OnBeforeDownload(w, b, d, c);
+ control.BeforeDownload += (w, b, d, c, a) => a.Value = a.Value = downloadHandler.OnBeforeDownload(w, b, d, c);
+ control.BeforeUnloadDialog += (w, b, m, r, c, a) => a.Value = javaScriptDialogHandler.OnBeforeUnloadDialog(w, b, m, r, c);
control.CanDownload += (w, b, u, r, a) => a.Value = downloadHandler.CanDownload(w, b, u, r);
control.ContextCreated += (w, b, f) => renderProcessMessageHandler.OnContextCreated(w, b, f);
control.ContextReleased += (w, b, f) => renderProcessMessageHandler.OnContextReleased(w, b, f);
+ control.DialogClosed += (w, b) => javaScriptDialogHandler.OnDialogClosed(w, b);
control.DownloadUpdated += (w, b, d, c) => downloadHandler.OnDownloadUpdated(w, b, d, c);
+ control.DragEnterCefSharp += (w, b, d, m, a) => a.Value = dragHandler.OnDragEnter(w, b, d, m);
+ control.DraggableRegionsChanged += (w, b, f, r) => dragHandler.OnDraggableRegionsChanged(w, b, f, r);
control.FaviconUrlChanged += (w, b, u) => displayHandler.OnFaviconUrlChange(w, b, u);
- control.FileDialogRequested += (w, b, m, t, d, f, c) => dialogHandler.OnFileDialog(w, b, m, t, d, f, c);
+ control.FileDialogRequested += (w, b, m, t, p, f, e, d, c) => dialogHandler.OnFileDialog(w, b, m, t, p, f, e, d, c);
control.FocusedNodeChanged += (w, b, f, n) => renderProcessMessageHandler.OnFocusedNodeChanged(w, b, f, n);
+ control.GotFocusCefSharp += (w, b) => focusHandler.OnGotFocus(w, b);
control.IsBrowserInitializedChanged += Control_IsBrowserInitializedChanged;
+ control.JavaScriptDialog += (IWebBrowser w, IBrowser b, string u, CefJsDialogType t, string m, string p, IJsDialogCallback c, ref bool s, GenericEventArgs a) => a.Value = javaScriptDialogHandler.OnJSDialog(w, b, u, t, m, p, c, ref s);
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.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);
control.PreKeyEvent += (IWebBrowser w, IBrowser b, KeyType t, int k, int n, CefEventFlags m, bool i, ref bool s, GenericEventArgs a) => a.Value = keyboardHandler.OnPreKeyEvent(w, b, t, k, n, m, i, ref s);
+ control.ResetDialogState += (w, b) => javaScriptDialogHandler.OnResetDialogState(w, b);
control.ResourceRequestHandlerRequired += (IWebBrowser w, IBrowser b, IFrame f, IRequest r, bool n, bool d, string i, ref bool h, ResourceRequestEventArgs a) => a.Handler = requestHandler.GetResourceRequestHandler(w, b, f, r, n, d, i, ref h);
+ control.SetFocus += (w, b, s, a) => a.Value = focusHandler.OnSetFocus(w, b, s);
+ control.TakeFocus += (w, b, n) => focusHandler.OnTakeFocus(w, b, n);
control.TitleChanged += (o, e) => TitleChanged?.Invoke(e.Title);
control.UncaughtExceptionEvent += (w, b, f, e) => renderProcessMessageHandler.OnUncaughtException(w, b, f, e);
diff --git a/SafeExamBrowser.Browser/BrowserIconResource.cs b/SafeExamBrowser.Browser/BrowserIconResource.cs
index b0896ce..350bbc6 100644
--- a/SafeExamBrowser.Browser/BrowserIconResource.cs
+++ b/SafeExamBrowser.Browser/BrowserIconResource.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/BrowserWindow.cs b/SafeExamBrowser.Browser/BrowserWindow.cs
index dc67d5a..54d68d7 100644
--- a/SafeExamBrowser.Browser/BrowserWindow.cs
+++ b/SafeExamBrowser.Browser/BrowserWindow.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -157,6 +157,9 @@ namespace SafeExamBrowser.Browser
var displayHandler = new DisplayHandler();
var downloadLogger = logger.CloneFor($"{nameof(DownloadHandler)} #{Id}");
var downloadHandler = new DownloadHandler(appConfig, downloadLogger, settings, WindowSettings);
+ var dragHandler = new DragHandler();
+ var focusHandler = new FocusHandler();
+ var javaScriptDialogHandler = new JavaScriptDialogHandler();
var keyboardHandler = new KeyboardHandler();
var renderHandler = new RenderProcessMessageHandler(appConfig, clipboard, keyGenerator, settings, text);
var requestFilter = new RequestFilter();
@@ -181,6 +184,7 @@ namespace SafeExamBrowser.Browser
downloadHandler.ConfigurationDownloadRequested += DownloadHandler_ConfigurationDownloadRequested;
downloadHandler.DownloadAborted += DownloadHandler_DownloadAborted;
downloadHandler.DownloadUpdated += DownloadHandler_DownloadUpdated;
+ javaScriptDialogHandler.DialogRequested += JavaScriptDialogHandler_DialogRequested;
keyboardHandler.FindRequested += KeyboardHandler_FindRequested;
keyboardHandler.FocusAddressBarRequested += KeyboardHandler_FocusAddressBarRequested;
keyboardHandler.HomeNavigationRequested += HomeNavigationRequested;
@@ -195,7 +199,19 @@ namespace SafeExamBrowser.Browser
InitializeRequestFilter(requestFilter);
- Control = new BrowserControl(clipboard, cefSharpControl, dialogHandler, displayHandler, downloadHandler, keyboardHandler, controlLogger, renderHandler, requestHandler);
+ Control = new BrowserControl(
+ clipboard,
+ cefSharpControl,
+ dialogHandler,
+ displayHandler,
+ downloadHandler,
+ dragHandler,
+ focusHandler,
+ javaScriptDialogHandler,
+ keyboardHandler,
+ controlLogger,
+ renderHandler,
+ requestHandler);
Control.AddressChanged += Control_AddressChanged;
Control.LoadFailed += Control_LoadFailed;
Control.LoadingStateChanged += Control_LoadingStateChanged;
@@ -488,6 +504,20 @@ namespace SafeExamBrowser.Browser
}
}
+ private void JavaScriptDialogHandler_DialogRequested(JavaScriptDialogRequestedEventArgs args)
+ {
+ logger.Debug($"A JavaScript dialog of type '{args.Type}' has been requested...");
+
+ if (args.Type == JavaScriptDialogType.LeavePage)
+ {
+ args.Success = RequestPageLeave();
+ }
+ else
+ {
+ args.Success = RequestPageReload();
+ }
+ }
+
private void KeyboardHandler_FindRequested()
{
if (settings.AllowFind)
@@ -642,29 +672,61 @@ namespace SafeExamBrowser.Browser
private void ReloadRequested()
{
+ logger.Debug("A reload of the current page has been requested...");
+
+ if (RequestPageReload())
+ {
+ Control.Reload();
+ }
+ }
+
+ private bool RequestPageLeave()
+ {
+ var allow = false;
+ var result = messageBox.Show(TextKey.MessageBox_PageLeaveConfirmation, TextKey.MessageBox_PageLeaveConfirmationTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question, window);
+
+ if (result == MessageBoxResult.Yes)
+ {
+ allow = true;
+ logger.Debug("The page leave has been granted by the user.");
+ }
+ else
+ {
+ logger.Debug("The page leave has been aborted by the user.");
+ }
+
+ return allow;
+ }
+
+ private bool RequestPageReload()
+ {
+ var allow = false;
+
if (WindowSettings.AllowReloading && WindowSettings.ShowReloadWarning)
{
- var result = messageBox.Show(TextKey.MessageBox_ReloadConfirmation, TextKey.MessageBox_ReloadConfirmationTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question, window);
+ var result = messageBox.Show(TextKey.MessageBox_PageReloadConfirmation, TextKey.MessageBox_PageReloadConfirmationTitle, MessageBoxAction.YesNo, MessageBoxIcon.Question, window);
if (result == MessageBoxResult.Yes)
{
- logger.Debug("The user confirmed reloading the current page...");
- Control.Reload();
+ allow = true;
+ logger.Debug("The page reload has been granted by the user.");
}
else
{
- logger.Debug("The user aborted reloading the current page.");
+ logger.Debug("The page reload has been aborted by the user.");
}
}
else if (WindowSettings.AllowReloading)
{
- logger.Debug("Reloading current page...");
- Control.Reload();
+ allow = true;
+ logger.Debug("The page reload has been automatically granted.");
}
else
{
- logger.Debug("Blocked reload attempt, as the user is not allowed to reload web pages.");
+ logger.Debug("The page reload has been blocked, as the user is not allowed to reload web pages.");
}
+
+ return allow;
}
private void ShowDownUploadNotAllowedMessage(bool isDownload = true)
diff --git a/SafeExamBrowser.Browser/Clipboard.cs b/SafeExamBrowser.Browser/Clipboard.cs
index 151e21e..157c358 100644
--- a/SafeExamBrowser.Browser/Clipboard.cs
+++ b/SafeExamBrowser.Browser/Clipboard.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -32,7 +32,22 @@ namespace SafeExamBrowser.Browser
internal void Process(JavascriptMessageReceivedEventArgs message)
{
-
+ if (settings.UseIsolatedClipboard)
+ {
+ try
+ {
+ var data = message.ConvertMessageTo();
+
+ if (data != default && data.Type == "Clipboard" && TrySetContent(data.Content))
+ {
+ Task.Run(() => Changed?.Invoke(data.Id));
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error($"Failed to process browser message '{message}'!", e);
+ }
+ }
}
private bool TrySetContent(object value)
diff --git a/SafeExamBrowser.Browser/Content/Api.js b/SafeExamBrowser.Browser/Content/Api.js
index c2c1c9a..2210bf7 100644
--- a/SafeExamBrowser.Browser/Content/Api.js
+++ b/SafeExamBrowser.Browser/Content/Api.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Content/Clipboard.js b/SafeExamBrowser.Browser/Content/Clipboard.js
index a246187..1b1f94b 100644
--- a/SafeExamBrowser.Browser/Content/Clipboard.js
+++ b/SafeExamBrowser.Browser/Content/Clipboard.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zrich, IT Services
+ * Copyright (c) 2025 ETH Zrich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Content/ContentLoader.cs b/SafeExamBrowser.Browser/Content/ContentLoader.cs
index bb7e19c..b88854d 100644
--- a/SafeExamBrowser.Browser/Content/ContentLoader.cs
+++ b/SafeExamBrowser.Browser/Content/ContentLoader.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Content/PageZoom.js b/SafeExamBrowser.Browser/Content/PageZoom.js
index e9b2012..0345dc2 100644
--- a/SafeExamBrowser.Browser/Content/PageZoom.js
+++ b/SafeExamBrowser.Browser/Content/PageZoom.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zrich, IT Services
+ * Copyright (c) 2025 ETH Zrich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/ClipboardChangedEventHandler.cs b/SafeExamBrowser.Browser/Events/ClipboardChangedEventHandler.cs
index e6baad3..c6886bb 100644
--- a/SafeExamBrowser.Browser/Events/ClipboardChangedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/ClipboardChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/DialogRequestedEventArgs.cs b/SafeExamBrowser.Browser/Events/DialogRequestedEventArgs.cs
index 689da60..27ac2d6 100644
--- a/SafeExamBrowser.Browser/Events/DialogRequestedEventArgs.cs
+++ b/SafeExamBrowser.Browser/Events/DialogRequestedEventArgs.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/DialogRequestedEventHandler.cs b/SafeExamBrowser.Browser/Events/DialogRequestedEventHandler.cs
index f56a02e..871d51d 100644
--- a/SafeExamBrowser.Browser/Events/DialogRequestedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/DialogRequestedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/DownloadAbortedEventHandler.cs b/SafeExamBrowser.Browser/Events/DownloadAbortedEventHandler.cs
index 2e85d86..9abd4b6 100644
--- a/SafeExamBrowser.Browser/Events/DownloadAbortedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/DownloadAbortedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/DownloadUpdatedEventHandler.cs b/SafeExamBrowser.Browser/Events/DownloadUpdatedEventHandler.cs
index 2f40368..25a24db 100644
--- a/SafeExamBrowser.Browser/Events/DownloadUpdatedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/DownloadUpdatedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs b/SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs
index 978f50d..6f09ab9 100644
--- a/SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs b/SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs
index 001b9f0..22107b4 100644
--- a/SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs
+++ b/SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs b/SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs
index 4d80490..b13da61 100644
--- a/SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs b/SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs
index b122c8f..54e8c64 100644
--- a/SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/ResetRequestedEventHandler.cs b/SafeExamBrowser.Browser/Events/ResetRequestedEventHandler.cs
index a1e7ddd..2de3bd9 100644
--- a/SafeExamBrowser.Browser/Events/ResetRequestedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/ResetRequestedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/UrlEventHandler.cs b/SafeExamBrowser.Browser/Events/UrlEventHandler.cs
index 0ca49a9..c770ae5 100644
--- a/SafeExamBrowser.Browser/Events/UrlEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/UrlEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Events/WindowClosedEventHandler.cs b/SafeExamBrowser.Browser/Events/WindowClosedEventHandler.cs
index f1ca1a1..bfcfec4 100644
--- a/SafeExamBrowser.Browser/Events/WindowClosedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Events/WindowClosedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Filters/RequestFilter.cs b/SafeExamBrowser.Browser/Filters/RequestFilter.cs
index 83379a0..9d70070 100644
--- a/SafeExamBrowser.Browser/Filters/RequestFilter.cs
+++ b/SafeExamBrowser.Browser/Filters/RequestFilter.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Filters/RuleFactory.cs b/SafeExamBrowser.Browser/Filters/RuleFactory.cs
index 056d6fa..3b8ddff 100644
--- a/SafeExamBrowser.Browser/Filters/RuleFactory.cs
+++ b/SafeExamBrowser.Browser/Filters/RuleFactory.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs b/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs
index 2f23947..b991b5a 100644
--- a/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs
+++ b/SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs b/SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs
index c46d86c..818f0d7 100644
--- a/SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs
+++ b/SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs b/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs
index e8ccaa6..0309e0b 100644
--- a/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Handlers/DialogHandler.cs b/SafeExamBrowser.Browser/Handlers/DialogHandler.cs
index 75ff993..0120021 100644
--- a/SafeExamBrowser.Browser/Handlers/DialogHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/DialogHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -18,7 +18,16 @@ namespace SafeExamBrowser.Browser.Handlers
{
internal event DialogRequestedEventHandler DialogRequested;
- public bool OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List acceptFilters, IFileDialogCallback callback)
+ public bool OnFileDialog(
+ IWebBrowser webBrowser,
+ IBrowser browser,
+ CefFileDialogMode mode,
+ string title,
+ string defaultFilePath,
+ IReadOnlyCollection acceptFilters,
+ IReadOnlyCollection acceptExtensions,
+ IReadOnlyCollection acceptDescriptions,
+ IFileDialogCallback callback)
{
var args = new DialogRequestedEventArgs
{
diff --git a/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs b/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
index 80ae155..928473a 100644
--- a/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/DisplayHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs b/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs
index 2f78650..4f35be5 100644
--- a/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/DownloadHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -50,7 +50,7 @@ namespace SafeExamBrowser.Browser.Handlers
return true;
}
- public void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
+ public bool OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
{
var fileExtension = Path.GetExtension(downloadItem.SuggestedFileName);
var isConfigurationFile = false;
@@ -86,6 +86,8 @@ namespace SafeExamBrowser.Browser.Handlers
logger.Info($"Aborted download request{(windowSettings.UrlPolicy.CanLog() ? $" for '{url}'" : "")}, as downloading is not allowed.");
Task.Run(() => DownloadAborted?.Invoke());
}
+
+ return true;
}
public void OnDownloadUpdated(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
@@ -100,6 +102,8 @@ namespace SafeExamBrowser.Browser.Handlers
FullPath = downloadItem.FullPath,
IsCancelled = downloadItem.IsCancelled,
IsComplete = downloadItem.IsComplete,
+ IsIndeterminate = downloadItem.PercentComplete < 0,
+ Size = downloadItem.ReceivedBytes,
Url = downloadItem.Url
};
diff --git a/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs b/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs
index f197ba9..c93d17e 100644
--- a/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Handlers/RenderProcessMessageHandler.cs b/SafeExamBrowser.Browser/Handlers/RenderProcessMessageHandler.cs
index 3f16250..78a025b 100644
--- a/SafeExamBrowser.Browser/Handlers/RenderProcessMessageHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/RenderProcessMessageHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs
index 5baa8f7..9d00b8f 100644
--- a/SafeExamBrowser.Browser/Handlers/RequestHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/RequestHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
index d70de7e..5a75315 100644
--- a/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
+++ b/SafeExamBrowser.Browser/Handlers/ResourceHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Properties/AssemblyInfo.cs b/SafeExamBrowser.Browser/Properties/AssemblyInfo.cs
index a1c6e15..c9045c0 100644
--- a/SafeExamBrowser.Browser/Properties/AssemblyInfo.cs
+++ b/SafeExamBrowser.Browser/Properties/AssemblyInfo.cs
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Safe Exam Browser")]
[assembly: AssemblyCompany("ETH Zürich")]
[assembly: AssemblyProduct("SafeExamBrowser.Browser")]
-[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")]
+[assembly: AssemblyCopyright("Copyright © 2025 ETH Zürich, IT Services")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
diff --git a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
index cf59044..c3a1bf8 100644
--- a/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
+++ b/SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj
@@ -1,8 +1,8 @@
-
-
-
+
+
+
Debug
@@ -53,14 +53,14 @@
prompt
-
- ..\packages\CefSharp.Common.121.3.130\lib\net462\CefSharp.dll
+
+ ..\packages\CefSharp.Common.131.3.50\lib\net462\CefSharp.dll
-
- ..\packages\CefSharp.Common.121.3.130\lib\net462\CefSharp.Core.dll
+
+ ..\packages\CefSharp.Common.131.3.50\lib\net462\CefSharp.Core.dll
-
- ..\packages\CefSharp.WinForms.121.3.130\lib\net462\CefSharp.WinForms.dll
+
+ ..\packages\CefSharp.WinForms.131.3.50\lib\net462\CefSharp.WinForms.dll
..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
@@ -87,6 +87,9 @@
+
+
+
@@ -103,6 +106,8 @@
+
+
@@ -118,25 +123,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -209,10 +227,10 @@
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/SafeExamBrowser.Browser/Wrapper/CefSharpBrowserControl.cs b/SafeExamBrowser.Browser/Wrapper/CefSharpBrowserControl.cs
index 9f1358e..cfa16e0 100644
--- a/SafeExamBrowser.Browser/Wrapper/CefSharpBrowserControl.cs
+++ b/SafeExamBrowser.Browser/Wrapper/CefSharpBrowserControl.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using CefSharp;
+using CefSharp.Enums;
using CefSharp.WinForms;
using SafeExamBrowser.Browser.Handlers;
using SafeExamBrowser.Browser.Wrapper.Events;
@@ -20,18 +21,27 @@ namespace SafeExamBrowser.Browser.Wrapper
public event AuthCredentialsEventHandler AuthCredentialsRequired;
public event BeforeBrowseEventHandler BeforeBrowse;
public event BeforeDownloadEventHandler BeforeDownload;
+ public event BeforeUnloadDialogEventHandler BeforeUnloadDialog;
public event CanDownloadEventHandler CanDownload;
public event ContextCreatedEventHandler ContextCreated;
public event ContextReleasedEventHandler ContextReleased;
+ public event DialogClosedEventHandler DialogClosed;
public event DownloadUpdatedEventHandler DownloadUpdated;
+ public event DragEnterEventHandler DragEnterCefSharp;
+ public event DraggableRegionsChangedEventHandler DraggableRegionsChanged;
public event FaviconUrlChangedEventHandler FaviconUrlChanged;
public event FileDialogRequestedEventHandler FileDialogRequested;
public event FocusedNodeChangedEventHandler FocusedNodeChanged;
+ public event GotFocusEventHandler GotFocusCefSharp;
+ public event JavaScriptDialogEventHandler JavaScriptDialog;
public event KeyEventHandler KeyEvent;
public event LoadingProgressChangedEventHandler LoadingProgressChanged;
public event OpenUrlFromTabEventHandler OpenUrlFromTab;
public event PreKeyEventHandler PreKeyEvent;
+ public event ResetDialogStateEventHandler ResetDialogState;
public event ResourceRequestEventHandler ResourceRequestHandlerRequired;
+ public event SetFocusEventHandler SetFocus;
+ public event TakeFocusEventHandler TakeFocus;
public event UncaughtExceptionEventHandler UncaughtExceptionEvent;
public CefSharpBrowserControl(ILifeSpanHandler lifeSpanHandler, string url) : base(url)
@@ -39,6 +49,9 @@ namespace SafeExamBrowser.Browser.Wrapper
DialogHandler = new DialogHandlerSwitch();
DisplayHandler = new DisplayHandlerSwitch();
DownloadHandler = new DownloadHandlerSwitch();
+ DragHandler = new DragHandlerSwitch();
+ FocusHandler = new FocusHandlerSwitch();
+ JsDialogHandler = new JavaScriptDialogHandlerSwitch();
KeyboardHandler = new KeyboardHandlerSwitch();
LifeSpanHandler = lifeSpanHandler;
MenuHandler = new ContextMenuHandler();
@@ -66,9 +79,14 @@ namespace SafeExamBrowser.Browser.Wrapper
BeforeBrowse?.Invoke(webBrowser, browser, frame, request, userGesture, isRedirect, args);
}
- public void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
+ public void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback, GenericEventArgs args)
{
- BeforeDownload?.Invoke(webBrowser, browser, downloadItem, callback);
+ BeforeDownload?.Invoke(webBrowser, browser, downloadItem, callback, args);
+ }
+
+ public void OnBeforeUnloadDialog(IWebBrowser webBrowser, IBrowser browser, string message, bool isReload, IJsDialogCallback callback, GenericEventArgs args)
+ {
+ BeforeUnloadDialog?.Invoke(webBrowser, browser, message, isReload, callback, args);
}
public void OnCanDownload(IWebBrowser webBrowser, IBrowser browser, string url, string requestMethod, GenericEventArgs args)
@@ -86,19 +104,34 @@ namespace SafeExamBrowser.Browser.Wrapper
ContextReleased?.Invoke(webBrowser, browser, frame);
}
+ public void OnDialogClosed(IWebBrowser webBrowser, IBrowser browser)
+ {
+ DialogClosed?.Invoke(webBrowser, browser);
+ }
+
public void OnDownloadUpdated(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
{
DownloadUpdated?.Invoke(webBrowser, browser, downloadItem, callback);
}
+ public void OnDragEnter(IWebBrowser webBrowser, IBrowser browser, IDragData dragData, DragOperationsMask mask, GenericEventArgs args)
+ {
+ DragEnterCefSharp?.Invoke(webBrowser, browser, dragData, mask, args);
+ }
+
+ public void OnDraggableRegionsChanged(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IList regions)
+ {
+ DraggableRegionsChanged?.Invoke(webBrowser, browser, frame, regions);
+ }
+
public void OnFaviconUrlChange(IWebBrowser webBrowser, IBrowser browser, IList urls)
{
FaviconUrlChanged?.Invoke(webBrowser, browser, urls);
}
- public void OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List acceptFilters, IFileDialogCallback callback)
+ public void OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, IReadOnlyCollection acceptFilters, IReadOnlyCollection acceptExtensions, IReadOnlyCollection acceptDescriptions, IFileDialogCallback callback)
{
- FileDialogRequested?.Invoke(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, callback);
+ FileDialogRequested?.Invoke(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, acceptExtensions, acceptDescriptions, callback);
}
public void OnFocusedNodeChanged(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IDomNode node)
@@ -106,6 +139,16 @@ namespace SafeExamBrowser.Browser.Wrapper
FocusedNodeChanged?.Invoke(webBrowser, browser, frame, node);
}
+ public void OnGotFocus(IWebBrowser webBrowser, IBrowser browser)
+ {
+ GotFocusCefSharp?.Invoke(webBrowser, browser);
+ }
+
+ public void OnJavaScriptDialog(IWebBrowser webBrowser, IBrowser browser, string originUrl, CefJsDialogType type, string message, string promptText, IJsDialogCallback callback, ref bool suppress, GenericEventArgs args)
+ {
+ JavaScriptDialog?.Invoke(webBrowser, browser, originUrl, type, message, promptText, callback, ref suppress, args);
+ }
+
public void OnKeyEvent(IWebBrowser webBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
{
KeyEvent?.Invoke(webBrowser, browser, type, windowsKeyCode, nativeKeyCode, modifiers, isSystemKey);
@@ -126,6 +169,21 @@ namespace SafeExamBrowser.Browser.Wrapper
PreKeyEvent?.Invoke(webBrowser, browser, type, windowsKeyCode, nativeKeyCode, modifiers, isSystemKey, ref isKeyboardShortcut, args);
}
+ public void OnResetDialogState(IWebBrowser webBrowser, IBrowser browser)
+ {
+ ResetDialogState?.Invoke(webBrowser, browser);
+ }
+
+ public void OnSetFocus(IWebBrowser webBrowser, IBrowser browser, CefFocusSource source, GenericEventArgs args)
+ {
+ SetFocus?.Invoke(webBrowser, browser, source, args);
+ }
+
+ public void OnTakeFocus(IWebBrowser webBrowser, IBrowser browser, bool next)
+ {
+ TakeFocus?.Invoke(webBrowser, browser, next);
+ }
+
public void OnUncaughtException(IWebBrowser webBrowser, IBrowser browser, IFrame frame, JavascriptException exception)
{
UncaughtExceptionEvent?.Invoke(webBrowser, browser, frame, exception);
diff --git a/SafeExamBrowser.Browser/Wrapper/CefSharpPopupControl.cs b/SafeExamBrowser.Browser/Wrapper/CefSharpPopupControl.cs
index d552666..cc38a3b 100644
--- a/SafeExamBrowser.Browser/Wrapper/CefSharpPopupControl.cs
+++ b/SafeExamBrowser.Browser/Wrapper/CefSharpPopupControl.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using CefSharp;
+using CefSharp.Enums;
using CefSharp.WinForms.Host;
using SafeExamBrowser.Browser.Wrapper.Events;
@@ -18,18 +19,27 @@ namespace SafeExamBrowser.Browser.Wrapper
public event AuthCredentialsEventHandler AuthCredentialsRequired;
public event BeforeBrowseEventHandler BeforeBrowse;
public event BeforeDownloadEventHandler BeforeDownload;
+ public event BeforeUnloadDialogEventHandler BeforeUnloadDialog;
public event CanDownloadEventHandler CanDownload;
public event ContextCreatedEventHandler ContextCreated;
public event ContextReleasedEventHandler ContextReleased;
+ public event DialogClosedEventHandler DialogClosed;
public event DownloadUpdatedEventHandler DownloadUpdated;
+ public event DragEnterEventHandler DragEnterCefSharp;
+ public event DraggableRegionsChangedEventHandler DraggableRegionsChanged;
public event FaviconUrlChangedEventHandler FaviconUrlChanged;
public event FileDialogRequestedEventHandler FileDialogRequested;
public event FocusedNodeChangedEventHandler FocusedNodeChanged;
+ public event GotFocusEventHandler GotFocusCefSharp;
+ public event JavaScriptDialogEventHandler JavaScriptDialog;
public event KeyEventHandler KeyEvent;
public event LoadingProgressChangedEventHandler LoadingProgressChanged;
public event OpenUrlFromTabEventHandler OpenUrlFromTab;
public event PreKeyEventHandler PreKeyEvent;
+ public event ResetDialogStateEventHandler ResetDialogState;
public event ResourceRequestEventHandler ResourceRequestHandlerRequired;
+ public event SetFocusEventHandler SetFocus;
+ public event TakeFocusEventHandler TakeFocus;
public event UncaughtExceptionEventHandler UncaughtExceptionEvent;
void ICefSharpControl.Dispose(bool disposing)
@@ -60,9 +70,14 @@ namespace SafeExamBrowser.Browser.Wrapper
BeforeBrowse?.Invoke(webBrowser, browser, frame, request, userGesture, isRedirect, args);
}
- public void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
+ public void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback, GenericEventArgs args)
{
- BeforeDownload?.Invoke(webBrowser, browser, downloadItem, callback);
+ BeforeDownload?.Invoke(webBrowser, browser, downloadItem, callback, args);
+ }
+
+ public void OnBeforeUnloadDialog(IWebBrowser webBrowser, IBrowser browser, string message, bool isReload, IJsDialogCallback callback, GenericEventArgs args)
+ {
+ BeforeUnloadDialog?.Invoke(webBrowser, browser, message, isReload, callback, args);
}
public void OnCanDownload(IWebBrowser webBrowser, IBrowser browser, string url, string requestMethod, GenericEventArgs args)
@@ -80,19 +95,34 @@ namespace SafeExamBrowser.Browser.Wrapper
ContextReleased?.Invoke(webBrowser, browser, frame);
}
+ public void OnDialogClosed(IWebBrowser webBrowser, IBrowser browser)
+ {
+ DialogClosed?.Invoke(webBrowser, browser);
+ }
+
public void OnDownloadUpdated(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
{
DownloadUpdated?.Invoke(webBrowser, browser, downloadItem, callback);
}
+ public void OnDragEnter(IWebBrowser webBrowser, IBrowser browser, IDragData dragData, DragOperationsMask mask, GenericEventArgs args)
+ {
+ DragEnterCefSharp?.Invoke(webBrowser, browser, dragData, mask, args);
+ }
+
+ public void OnDraggableRegionsChanged(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IList regions)
+ {
+ DraggableRegionsChanged?.Invoke(webBrowser, browser, frame, regions);
+ }
+
public void OnFaviconUrlChange(IWebBrowser webBrowser, IBrowser browser, IList urls)
{
FaviconUrlChanged?.Invoke(webBrowser, browser, urls);
}
- public void OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List acceptFilters, IFileDialogCallback callback)
+ public void OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, IReadOnlyCollection acceptFilters, IReadOnlyCollection acceptExtensions, IReadOnlyCollection acceptDescriptions, IFileDialogCallback callback)
{
- FileDialogRequested?.Invoke(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, callback);
+ FileDialogRequested?.Invoke(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, acceptExtensions, acceptDescriptions, callback);
}
public void OnFocusedNodeChanged(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IDomNode node)
@@ -100,6 +130,16 @@ namespace SafeExamBrowser.Browser.Wrapper
FocusedNodeChanged?.Invoke(webBrowser, browser, frame, node);
}
+ public void OnGotFocus(IWebBrowser webBrowser, IBrowser browser)
+ {
+ GotFocusCefSharp?.Invoke(webBrowser, browser);
+ }
+
+ public void OnJavaScriptDialog(IWebBrowser webBrowser, IBrowser browser, string originUrl, CefJsDialogType type, string message, string promptText, IJsDialogCallback callback, ref bool suppress, GenericEventArgs args)
+ {
+ JavaScriptDialog?.Invoke(webBrowser, browser, originUrl, type, message, promptText, callback, ref suppress, args);
+ }
+
public void OnKeyEvent(IWebBrowser webBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
{
KeyEvent?.Invoke(webBrowser, browser, type, windowsKeyCode, nativeKeyCode, modifiers, isSystemKey);
@@ -120,6 +160,21 @@ namespace SafeExamBrowser.Browser.Wrapper
PreKeyEvent?.Invoke(webBrowser, browser, type, windowsKeyCode, nativeKeyCode, modifiers, isSystemKey, ref isKeyboardShortcut, args);
}
+ public void OnResetDialogState(IWebBrowser webBrowser, IBrowser browser)
+ {
+ ResetDialogState?.Invoke(webBrowser, browser);
+ }
+
+ public void OnSetFocus(IWebBrowser webBrowser, IBrowser browser, CefFocusSource source, GenericEventArgs args)
+ {
+ SetFocus?.Invoke(webBrowser, browser, source, args);
+ }
+
+ public void OnTakeFocus(IWebBrowser webBrowser, IBrowser browser, bool next)
+ {
+ TakeFocus?.Invoke(webBrowser, browser, next);
+ }
+
public void OnUncaughtException(IWebBrowser webBrowser, IBrowser browser, IFrame frame, JavascriptException exception)
{
UncaughtExceptionEvent?.Invoke(webBrowser, browser, frame, exception);
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/AuthCredentialsEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/AuthCredentialsEventHandler.cs
index ffa6d00..b4db821 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/AuthCredentialsEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/AuthCredentialsEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/BeforeBrowseEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/BeforeBrowseEventHandler.cs
index 9b0ff73..de3908d 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/BeforeBrowseEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/BeforeBrowseEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/BeforeDownloadEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/BeforeDownloadEventHandler.cs
index f84b6d2..da11652 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/BeforeDownloadEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/BeforeDownloadEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -10,5 +10,5 @@ using CefSharp;
namespace SafeExamBrowser.Browser.Wrapper.Events
{
- internal delegate void BeforeDownloadEventHandler(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback);
+ internal delegate bool BeforeDownloadEventHandler(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback, GenericEventArgs args);
}
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/CanDownloadEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/CanDownloadEventHandler.cs
index 97d661a..6abe259 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/CanDownloadEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/CanDownloadEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/ContextCreatedEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/ContextCreatedEventHandler.cs
index 80b2295..a7fcc84 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/ContextCreatedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/ContextCreatedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/ContextReleasedEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/ContextReleasedEventHandler.cs
index b9ebeb0..dda5ae4 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/ContextReleasedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/ContextReleasedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/DownloadUpdatedEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/DownloadUpdatedEventHandler.cs
index 89ec6a8..2dee682 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/DownloadUpdatedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/DownloadUpdatedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/FaviconUrlChangedEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/FaviconUrlChangedEventHandler.cs
index 4ccba6e..9275b9d 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/FaviconUrlChangedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/FaviconUrlChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/FileDialogRequestedEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/FileDialogRequestedEventHandler.cs
index 7f665b7..b212d52 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/FileDialogRequestedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/FileDialogRequestedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -11,5 +11,5 @@ using CefSharp;
namespace SafeExamBrowser.Browser.Wrapper.Events
{
- internal delegate void FileDialogRequestedEventHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List acceptFilters, IFileDialogCallback callback);
+ internal delegate void FileDialogRequestedEventHandler(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, IReadOnlyCollection acceptFilters, IReadOnlyCollection acceptExtensions, IReadOnlyCollection acceptDescriptions, IFileDialogCallback callback);
}
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/FocusedNodeChangedEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/FocusedNodeChangedEventHandler.cs
index c1e2e67..0f75e1f 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/FocusedNodeChangedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/FocusedNodeChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/GenericEventArgs.cs b/SafeExamBrowser.Browser/Wrapper/Events/GenericEventArgs.cs
index 4e957f4..3d07db6 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/GenericEventArgs.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/GenericEventArgs.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/KeyEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/KeyEventHandler.cs
index ce5f7e3..0a72e80 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/KeyEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/KeyEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/LoadingProgressChangedEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/LoadingProgressChangedEventHandler.cs
index 53d0dc3..2e6a3e2 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/LoadingProgressChangedEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/LoadingProgressChangedEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/OpenUrlFromTabEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/OpenUrlFromTabEventHandler.cs
index 91351a9..4560632 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/OpenUrlFromTabEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/OpenUrlFromTabEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/PreKeyEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/PreKeyEventHandler.cs
index 84de649..cb9098c 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/PreKeyEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/PreKeyEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventArgs.cs b/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventArgs.cs
index d3e64ff..8d01826 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventArgs.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventArgs.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventHandler.cs
index 430e7da..f47ed7c 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Events/UncaughtExceptionEventHandler.cs b/SafeExamBrowser.Browser/Wrapper/Events/UncaughtExceptionEventHandler.cs
index 1c832f2..b53c45a 100644
--- a/SafeExamBrowser.Browser/Wrapper/Events/UncaughtExceptionEventHandler.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Events/UncaughtExceptionEventHandler.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Extensions.cs b/SafeExamBrowser.Browser/Wrapper/Extensions.cs
index 10003ef..124214d 100644
--- a/SafeExamBrowser.Browser/Wrapper/Extensions.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Extensions.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Handlers/DialogHandlerSwitch.cs b/SafeExamBrowser.Browser/Wrapper/Handlers/DialogHandlerSwitch.cs
index f59ebbc..47639ca 100644
--- a/SafeExamBrowser.Browser/Wrapper/Handlers/DialogHandlerSwitch.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Handlers/DialogHandlerSwitch.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -15,19 +15,19 @@ namespace SafeExamBrowser.Browser.Wrapper.Handlers
{
internal class DialogHandlerSwitch : IDialogHandler
{
- public bool OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List acceptFilters, IFileDialogCallback callback)
+ public bool OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, IReadOnlyCollection acceptFilters, IReadOnlyCollection acceptExtensions, IReadOnlyCollection acceptDescriptions, IFileDialogCallback callback)
{
if (browser.IsPopup)
{
var control = ChromiumHostControl.FromBrowser(browser) as CefSharpPopupControl;
- control?.OnFileDialog(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, callback);
+ control?.OnFileDialog(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, acceptExtensions, acceptDescriptions, callback);
}
else
{
var control = ChromiumWebBrowser.FromBrowser(browser) as CefSharpBrowserControl;
- control?.OnFileDialog(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, callback);
+ control?.OnFileDialog(webBrowser, browser, mode, title, defaultFilePath, acceptFilters, acceptExtensions, acceptDescriptions, callback);
}
return true;
diff --git a/SafeExamBrowser.Browser/Wrapper/Handlers/DisplayHandlerSwitch.cs b/SafeExamBrowser.Browser/Wrapper/Handlers/DisplayHandlerSwitch.cs
index c954994..b615b51 100644
--- a/SafeExamBrowser.Browser/Wrapper/Handlers/DisplayHandlerSwitch.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Handlers/DisplayHandlerSwitch.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Handlers/DownloadHandlerSwitch.cs b/SafeExamBrowser.Browser/Wrapper/Handlers/DownloadHandlerSwitch.cs
index 4e3fcbf..0a14b4b 100644
--- a/SafeExamBrowser.Browser/Wrapper/Handlers/DownloadHandlerSwitch.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Handlers/DownloadHandlerSwitch.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -35,20 +35,24 @@ namespace SafeExamBrowser.Browser.Wrapper.Handlers
return args.Value;
}
- public void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
+ public bool OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
{
+ var args = new GenericEventArgs();
+
if (browser.IsPopup)
{
var control = ChromiumHostControl.FromBrowser(browser) as CefSharpPopupControl;
- control?.OnBeforeDownload(webBrowser, browser, downloadItem, callback);
+ control?.OnBeforeDownload(webBrowser, browser, downloadItem, callback, args);
}
else
{
var control = ChromiumWebBrowser.FromBrowser(browser) as CefSharpBrowserControl;
- control?.OnBeforeDownload(webBrowser, browser, downloadItem, callback);
+ control?.OnBeforeDownload(webBrowser, browser, downloadItem, callback, args);
}
+
+ return args.Value;
}
public void OnDownloadUpdated(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
diff --git a/SafeExamBrowser.Browser/Wrapper/Handlers/KeyboardHandlerSwitch.cs b/SafeExamBrowser.Browser/Wrapper/Handlers/KeyboardHandlerSwitch.cs
index e91ee84..a7460f0 100644
--- a/SafeExamBrowser.Browser/Wrapper/Handlers/KeyboardHandlerSwitch.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Handlers/KeyboardHandlerSwitch.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Handlers/RenderProcessMessageHandlerSwitch.cs b/SafeExamBrowser.Browser/Wrapper/Handlers/RenderProcessMessageHandlerSwitch.cs
index 979c8e4..ce48d60 100644
--- a/SafeExamBrowser.Browser/Wrapper/Handlers/RenderProcessMessageHandlerSwitch.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Handlers/RenderProcessMessageHandlerSwitch.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/Handlers/RequestHandlerSwitch.cs b/SafeExamBrowser.Browser/Wrapper/Handlers/RequestHandlerSwitch.cs
index cbff918..9a9e223 100644
--- a/SafeExamBrowser.Browser/Wrapper/Handlers/RequestHandlerSwitch.cs
+++ b/SafeExamBrowser.Browser/Wrapper/Handlers/RequestHandlerSwitch.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
diff --git a/SafeExamBrowser.Browser/Wrapper/ICefSharpControl.cs b/SafeExamBrowser.Browser/Wrapper/ICefSharpControl.cs
index 6e86f04..50ab911 100644
--- a/SafeExamBrowser.Browser/Wrapper/ICefSharpControl.cs
+++ b/SafeExamBrowser.Browser/Wrapper/ICefSharpControl.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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
@@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using CefSharp;
+using CefSharp.Enums;
using CefSharp.WinForms;
using SafeExamBrowser.Browser.Wrapper.Events;
using KeyEventHandler = SafeExamBrowser.Browser.Wrapper.Events.KeyEventHandler;
@@ -21,18 +22,27 @@ namespace SafeExamBrowser.Browser.Wrapper
event AuthCredentialsEventHandler AuthCredentialsRequired;
event BeforeBrowseEventHandler BeforeBrowse;
event BeforeDownloadEventHandler BeforeDownload;
+ event BeforeUnloadDialogEventHandler BeforeUnloadDialog;
event CanDownloadEventHandler CanDownload;
event ContextCreatedEventHandler ContextCreated;
event ContextReleasedEventHandler ContextReleased;
+ event DialogClosedEventHandler DialogClosed;
event DownloadUpdatedEventHandler DownloadUpdated;
+ event DragEnterEventHandler DragEnterCefSharp;
+ event DraggableRegionsChangedEventHandler DraggableRegionsChanged;
event FaviconUrlChangedEventHandler FaviconUrlChanged;
event FileDialogRequestedEventHandler FileDialogRequested;
event FocusedNodeChangedEventHandler FocusedNodeChanged;
+ event GotFocusEventHandler GotFocusCefSharp;
+ event JavaScriptDialogEventHandler JavaScriptDialog;
event KeyEventHandler KeyEvent;
event LoadingProgressChangedEventHandler LoadingProgressChanged;
event OpenUrlFromTabEventHandler OpenUrlFromTab;
event PreKeyEventHandler PreKeyEvent;
+ event ResetDialogStateEventHandler ResetDialogState;
event ResourceRequestEventHandler ResourceRequestHandlerRequired;
+ event SetFocusEventHandler SetFocus;
+ event TakeFocusEventHandler TakeFocus;
event UncaughtExceptionEventHandler UncaughtExceptionEvent;
void Dispose(bool disposing);
@@ -40,18 +50,27 @@ namespace SafeExamBrowser.Browser.Wrapper
void GetResourceRequestHandler(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling, ResourceRequestEventArgs args);
void Load(string address);
void OnBeforeBrowse(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect, GenericEventArgs args);
- void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback);
+ void OnBeforeDownload(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback, GenericEventArgs args);
+ void OnBeforeUnloadDialog(IWebBrowser webBrowser, IBrowser browser, string message, bool isReload, IJsDialogCallback callback, GenericEventArgs args);
void OnCanDownload(IWebBrowser webBrowser, IBrowser browser, string url, string requestMethod, GenericEventArgs args);
void OnContextCreated(IWebBrowser webBrowser, IBrowser browser, IFrame frame);
void OnContextReleased(IWebBrowser webBrowser, IBrowser browser, IFrame frame);
+ void OnDialogClosed(IWebBrowser webBrowser, IBrowser browser);
void OnDownloadUpdated(IWebBrowser webBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback);
+ void OnDragEnter(IWebBrowser webBrowser, IBrowser browser, IDragData dragData, DragOperationsMask mask, GenericEventArgs args);
+ void OnDraggableRegionsChanged(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IList regions);
void OnFaviconUrlChange(IWebBrowser webBrowser, IBrowser browser, IList urls);
- void OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, List acceptFilters, IFileDialogCallback callback);
+ void OnFileDialog(IWebBrowser webBrowser, IBrowser browser, CefFileDialogMode mode, string title, string defaultFilePath, IReadOnlyCollection acceptFilters, IReadOnlyCollection acceptExtensions, IReadOnlyCollection acceptDescriptions, IFileDialogCallback callback);
void OnFocusedNodeChanged(IWebBrowser webBrowser, IBrowser browser, IFrame frame, IDomNode node);
+ void OnGotFocus(IWebBrowser webBrowser, IBrowser browser);
+ void OnJavaScriptDialog(IWebBrowser webBrowser, IBrowser browser, string originUrl, CefJsDialogType type, string message, string promptText, IJsDialogCallback callback, ref bool suppress, GenericEventArgs args);
void OnKeyEvent(IWebBrowser webBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey);
void OnLoadingProgressChange(IWebBrowser webBrowser, IBrowser browser, double progress);
void OnOpenUrlFromTab(IWebBrowser webBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture, GenericEventArgs args);
void OnPreKeyEvent(IWebBrowser webBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut, GenericEventArgs args);
+ void OnResetDialogState(IWebBrowser webBrowser, IBrowser browser);
+ void OnSetFocus(IWebBrowser webBrowser, IBrowser browser, CefFocusSource source, GenericEventArgs args);
+ void OnTakeFocus(IWebBrowser webBrowser, IBrowser browser, bool next);
void OnUncaughtException(IWebBrowser webBrowser, IBrowser browser, IFrame frame, JavascriptException exception);
}
}
diff --git a/SafeExamBrowser.Browser/packages.config b/SafeExamBrowser.Browser/packages.config
index 153cba1..8ce2de0 100644
--- a/SafeExamBrowser.Browser/packages.config
+++ b/SafeExamBrowser.Browser/packages.config
@@ -1,9 +1,9 @@
-
-
-
-
+
+
+
+
diff --git a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs
index bb05d4c..9436300 100644
--- a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs
+++ b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs
@@ -1,49 +1,20 @@
/*
- * Copyright (c) 2024 ETH Zürich, IT Services
+ * Copyright (c) 2025 ETH Zürich, IT Services
*
* 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;
-using System.Collections.Generic;
-using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
-using SafeExamBrowser.Applications.Contracts;
-using SafeExamBrowser.Browser.Contracts;
-using SafeExamBrowser.Browser.Contracts.Events;
-using SafeExamBrowser.Client.Contracts;
-using SafeExamBrowser.Client.Operations.Events;
-using SafeExamBrowser.Communication.Contracts.Data;
-using SafeExamBrowser.Communication.Contracts.Events;
-using SafeExamBrowser.Communication.Contracts.Hosts;
+using SafeExamBrowser.Client.Responsibilities;
using SafeExamBrowser.Communication.Contracts.Proxies;
using SafeExamBrowser.Configuration.Contracts;
-using SafeExamBrowser.Configuration.Contracts.Cryptography;
-using SafeExamBrowser.Configuration.Contracts.Integrity;
using SafeExamBrowser.Core.Contracts.OperationModel;
-using SafeExamBrowser.Core.Contracts.OperationModel.Events;
-using SafeExamBrowser.I18n.Contracts;
+using SafeExamBrowser.Core.Contracts.ResponsibilityModel;
using SafeExamBrowser.Logging.Contracts;
-using SafeExamBrowser.Monitoring.Contracts.Applications;
-using SafeExamBrowser.Monitoring.Contracts.Display;
-using SafeExamBrowser.Monitoring.Contracts.System;
-using SafeExamBrowser.Server.Contracts;
-using SafeExamBrowser.Server.Contracts.Data;
-using SafeExamBrowser.Settings;
-using SafeExamBrowser.Settings.Monitoring;
-using SafeExamBrowser.Settings.UserInterface;
-using SafeExamBrowser.SystemComponents.Contracts.Network;
-using SafeExamBrowser.UserInterface.Contracts;
-using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
-using SafeExamBrowser.UserInterface.Contracts.MessageBox;
-using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Windows;
-using SafeExamBrowser.UserInterface.Contracts.Windows.Data;
-using SafeExamBrowser.WindowsApi.Contracts;
-using IWindow = SafeExamBrowser.UserInterface.Contracts.Windows.IWindow;
namespace SafeExamBrowser.Client.UnitTests
{
@@ -51,1093 +22,138 @@ namespace SafeExamBrowser.Client.UnitTests
public class ClientControllerTests
{
private AppConfig appConfig;
- private Mock actionCenter;
- private Mock applicationMonitor;
- private Mock browser;
- private Mock clientHost;
private ClientContext context;
- private Mock coordinator;
- private Mock displayMonitor;
- private Mock explorerShell;
- private Mock fileSystemDialog;
- private Mock hashAlgorithm;
- private Mock integrityModule;
private Mock logger;
- private Mock messageBox;
- private Mock networkAdapter;
private Mock operationSequence;
+ private Mock> responsibilities;
private Mock runtimeProxy;
- private Mock sentinel;
- private Mock server;
- private Guid sessionId;
- private AppSettings settings;
- private Mock shutdown;
private Mock splashScreen;
- private Mock taskbar;
- private Mock text;
- private Mock uiFactory;
private ClientController sut;
[TestInitialize]
public void Initialize()
{
- var valid = true;
-
appConfig = new AppConfig();
- actionCenter = new Mock();
- applicationMonitor = new Mock();
- browser = new Mock();
- clientHost = new Mock();
context = new ClientContext();
- coordinator = new Mock();
- displayMonitor = new Mock();
- explorerShell = new Mock();
- fileSystemDialog = new Mock();
- hashAlgorithm = new Mock();
- integrityModule = new Mock();
logger = new Mock();
- messageBox = new Mock();
- networkAdapter = new Mock();
operationSequence = new Mock();
+ responsibilities = new Mock>();
runtimeProxy = new Mock();
- sentinel = new Mock();
- server = new Mock();
- sessionId = Guid.NewGuid();
- settings = new AppSettings();
- shutdown = new Mock();
splashScreen = new Mock();
- taskbar = new Mock();
- text = new Mock();
- uiFactory = new Mock();
- integrityModule.Setup(m => m.TryVerifySessionIntegrity(It.IsAny(), It.IsAny(), out valid)).Returns(true);
operationSequence.Setup(o => o.TryPerform()).Returns(OperationResult.Success);
+ operationSequence.Setup(o => o.TryRevert()).Returns(OperationResult.Success);
runtimeProxy.Setup(r => r.InformClientReady()).Returns(new CommunicationResult(true));
- uiFactory.Setup(u => u.CreateSplashScreen(It.IsAny())).Returns(new Mock().Object);
sut = new ClientController(
- actionCenter.Object,
- applicationMonitor.Object,
context,
- coordinator.Object,
- displayMonitor.Object,
- explorerShell.Object,
- fileSystemDialog.Object,
- hashAlgorithm.Object,
logger.Object,
- messageBox.Object,
- networkAdapter.Object,
operationSequence.Object,
+ responsibilities.Object,
runtimeProxy.Object,
- shutdown.Object,
- splashScreen.Object,
- sentinel.Object,
- taskbar.Object,
- text.Object,
- uiFactory.Object);
+ splashScreen.Object);
context.AppConfig = appConfig;
- context.Browser = browser.Object;
- context.ClientHost = clientHost.Object;
- context.IntegrityModule = integrityModule.Object;
- context.Server = server.Object;
- context.SessionId = sessionId;
- context.Settings = settings;
}
[TestMethod]
- public void ApplicationMonitor_MustCorrectlyHandleExplorerStartWithTaskbar()
+ public void Shutdown_MustDelegateResponsibilities()
{
- var boundsActionCenter = 0;
- var boundsTaskbar = 0;
- var height = 30;
var order = 0;
- var shell = 0;
- var workingArea = 0;
- settings.UserInterface.Taskbar.EnableTaskbar = true;
-
- actionCenter.Setup(a => a.InitializeBounds()).Callback(() => boundsActionCenter = ++order);
- explorerShell.Setup(e => e.Terminate()).Callback(() => shell = ++order);
- displayMonitor.Setup(w => w.InitializePrimaryDisplay(It.Is(h => h == height))).Callback(() => workingArea = ++order);
- taskbar.Setup(t => t.GetAbsoluteHeight()).Returns(height);
- taskbar.Setup(t => t.InitializeBounds()).Callback(() => boundsTaskbar = ++order);
-
- sut.TryStart();
- applicationMonitor.Raise(a => a.ExplorerStarted += null);
-
- actionCenter.Verify(a => a.InitializeBounds(), Times.Once);
- explorerShell.Verify(e => e.Terminate(), Times.Once);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == 0)), Times.Never);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == height)), Times.Once);
- taskbar.Verify(t => t.InitializeBounds(), Times.Once);
- taskbar.Verify(t => t.GetAbsoluteHeight(), Times.Once);
-
- Assert.IsTrue(shell == 1);
- Assert.IsTrue(workingArea == 2);
- Assert.IsTrue(boundsActionCenter == 3);
- Assert.IsTrue(boundsTaskbar == 4);
- }
-
- [TestMethod]
- public void ApplicationMonitor_MustCorrectlyHandleExplorerStartWithoutTaskbar()
- {
- var boundsActionCenter = 0;
- var boundsTaskbar = 0;
- var height = 30;
- var order = 0;
- var shell = 0;
- var workingArea = 0;
-
- settings.UserInterface.Taskbar.EnableTaskbar = false;
-
- actionCenter.Setup(a => a.InitializeBounds()).Callback(() => boundsActionCenter = ++order);
- explorerShell.Setup(e => e.Terminate()).Callback(() => shell = ++order);
- displayMonitor.Setup(w => w.InitializePrimaryDisplay(It.Is(h => h == 0))).Callback(() => workingArea = ++order);
- taskbar.Setup(t => t.GetAbsoluteHeight()).Returns(height);
- taskbar.Setup(t => t.InitializeBounds()).Callback(() => boundsTaskbar = ++order);
-
- sut.TryStart();
- applicationMonitor.Raise(a => a.ExplorerStarted += null);
-
- actionCenter.Verify(a => a.InitializeBounds(), Times.Once);
- explorerShell.Verify(e => e.Terminate(), Times.Once);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == 0)), Times.Once);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == height)), Times.Never);
- taskbar.Verify(t => t.InitializeBounds(), Times.Once);
- taskbar.Verify(t => t.GetAbsoluteHeight(), Times.Never);
-
- Assert.IsTrue(shell == 1);
- Assert.IsTrue(workingArea == 2);
- Assert.IsTrue(boundsActionCenter == 3);
- Assert.IsTrue(boundsTaskbar == 4);
- }
-
- [TestMethod]
- public void ApplicationMonitor_MustPermitApplicationIfChosenByUserAfterFailedTermination()
- {
- var lockScreen = new Mock();
- var result = new LockScreenResult();
-
- lockScreen.Setup(l => l.WaitForResult()).Returns(result);
- runtimeProxy.Setup(p => p.RequestShutdown()).Returns(new CommunicationResult(true));
- uiFactory
- .Setup(f => f.CreateLockScreen(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()))
- .Returns(lockScreen.Object)
- .Callback, LockScreenSettings>((m, t, o, s) => result.OptionId = o.First().Id);
-
- sut.TryStart();
- applicationMonitor.Raise(m => m.TerminationFailed += null, new List());
-
- runtimeProxy.Verify(p => p.RequestShutdown(), Times.Never);
- }
-
- [TestMethod]
- public void ApplicationMonitor_MustRequestShutdownIfChosenByUserAfterFailedTermination()
- {
- var lockScreen = new Mock();
- var result = new LockScreenResult();
-
- lockScreen.Setup(l => l.WaitForResult()).Returns(result);
- runtimeProxy.Setup(p => p.RequestShutdown()).Returns(new CommunicationResult(true));
- uiFactory
- .Setup(f => f.CreateLockScreen(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()))
- .Returns(lockScreen.Object)
- .Callback, LockScreenSettings>((m, t, o, s) => result.OptionId = o.Last().Id);
-
- sut.TryStart();
- applicationMonitor.Raise(m => m.TerminationFailed += null, new List());
-
- runtimeProxy.Verify(p => p.RequestShutdown(), Times.Once);
- }
-
- [TestMethod]
- public void ApplicationMonitor_MustShowLockScreenIfTerminationFailed()
- {
- var activator1 = new Mock();
- var activator2 = new Mock();
- var activator3 = new Mock();
- var lockScreen = new Mock();
- var result = new LockScreenResult();
- var order = 0;
- var pause = 0;
- var show = 0;
- var wait = 0;
- var close = 0;
- var resume = 0;
-
- activator1.Setup(a => a.Pause()).Callback(() => pause = ++order);
- activator1.Setup(a => a.Resume()).Callback(() => resume = ++order);
- context.Activators.Add(activator1.Object);
- context.Activators.Add(activator2.Object);
- context.Activators.Add(activator3.Object);
- lockScreen.Setup(l => l.Show()).Callback(() => show = ++order);
- lockScreen.Setup(l => l.WaitForResult()).Callback(() => wait = ++order).Returns(result);
- lockScreen.Setup(l => l.Close()).Callback(() => close = ++order);
- uiFactory
- .Setup(f => f.CreateLockScreen(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()))
- .Returns(lockScreen.Object);
-
- sut.TryStart();
- applicationMonitor.Raise(m => m.TerminationFailed += null, new List());
-
- activator1.Verify(a => a.Pause(), Times.Once);
- activator1.Verify(a => a.Resume(), Times.Once);
- activator2.Verify(a => a.Pause(), Times.Once);
- activator2.Verify(a => a.Resume(), Times.Once);
- activator3.Verify(a => a.Pause(), Times.Once);
- activator3.Verify(a => a.Resume(), Times.Once);
- lockScreen.Verify(l => l.Show(), Times.Once);
- lockScreen.Verify(l => l.WaitForResult(), Times.Once);
- lockScreen.Verify(l => l.Close(), Times.Once);
-
- Assert.IsTrue(pause == 1);
- Assert.IsTrue(show == 2);
- Assert.IsTrue(wait == 3);
- Assert.IsTrue(close == 4);
- Assert.IsTrue(resume == 5);
- }
-
- [TestMethod]
- public void ApplicationMonitor_MustValidateQuitPasswordIfTerminationFailed()
- {
- var hash = "12345";
- var lockScreen = new Mock();
- var result = new LockScreenResult { Password = "test" };
- var attempt = 0;
- var correct = new Random().Next(1, 50);
- var lockScreenResult = new Func(() => ++attempt == correct ? result : new LockScreenResult());
-
- context.Settings.Security.QuitPasswordHash = hash;
- hashAlgorithm.Setup(a => a.GenerateHashFor(It.Is(p => p == result.Password))).Returns(hash);
- lockScreen.Setup(l => l.WaitForResult()).Returns(lockScreenResult);
- uiFactory
- .Setup(f => f.CreateLockScreen(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()))
- .Returns(lockScreen.Object);
-
- sut.TryStart();
- applicationMonitor.Raise(m => m.TerminationFailed += null, new List());
-
- hashAlgorithm.Verify(a => a.GenerateHashFor(It.Is(p => p == result.Password)), Times.Once);
- hashAlgorithm.Verify(a => a.GenerateHashFor(It.Is(p => p != result.Password)), Times.Exactly(attempt - 1));
- messageBox.Verify(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.Is(w => w == lockScreen.Object)), Times.Exactly(attempt - 1));
- }
-
- [TestMethod]
- public void Browser_MustHandleUserIdentifierDetection()
- {
- var counter = 0;
- var identifier = "abc123";
-
- settings.SessionMode = SessionMode.Server;
- server.Setup(s => s.SendUserIdentifier(It.IsAny())).Returns(() => new ServerResponse(++counter == 3));
-
- sut.TryStart();
- browser.Raise(b => b.UserIdentifierDetected += null, identifier);
-
- server.Verify(s => s.SendUserIdentifier(It.Is(id => id == identifier)), Times.Exactly(3));
- }
-
- [TestMethod]
- public void Browser_MustTerminateIfRequested()
- {
- runtimeProxy.Setup(p => p.RequestShutdown()).Returns(new CommunicationResult(true));
-
- sut.TryStart();
- browser.Raise(b => b.TerminationRequested += null);
-
- runtimeProxy.Verify(p => p.RequestShutdown(), Times.Once);
- }
-
- [TestMethod]
- public void Communication_MustCorrectlyHandleExamSelection()
- {
- var args = new ExamSelectionRequestEventArgs
- {
- Exams = new List<(string id, string lms, string name, string url)> { ("", "", "", "") },
- RequestId = Guid.NewGuid()
- };
- var dialog = new Mock();
-
- dialog.Setup(d => d.Show(It.IsAny())).Returns(new ExamSelectionDialogResult { Success = true });
- uiFactory.Setup(f => f.CreateExamSelectionDialog(It.IsAny>())).Returns(dialog.Object);
-
- sut.TryStart();
- clientHost.Raise(c => c.ExamSelectionRequested += null, args);
-
- runtimeProxy.Verify(p => p.SubmitExamSelectionResult(It.Is(g => g == args.RequestId), true, null), Times.Once);
- uiFactory.Verify(f => f.CreateExamSelectionDialog(It.IsAny>()), Times.Once);
- }
-
- [TestMethod]
- public void Communication_MustCorrectlyHandleMessageBoxRequest()
- {
- var args = new MessageBoxRequestEventArgs
- {
- Action = (int) MessageBoxAction.YesNo,
- Icon = (int) MessageBoxIcon.Question,
- Message = "Some question to be answered",
- RequestId = Guid.NewGuid(),
- Title = "A Title"
- };
-
- messageBox.Setup(m => m.Show(
- It.Is(s => s == args.Message),
- It.Is(s => s == args.Title),
- It.Is(a => a == (MessageBoxAction) args.Action),
- It.Is(i => i == (MessageBoxIcon) args.Icon),
- It.IsAny())).Returns(MessageBoxResult.No);
-
- sut.TryStart();
- clientHost.Raise(c => c.MessageBoxRequested += null, args);
-
- runtimeProxy.Verify(p => p.SubmitMessageBoxResult(
- It.Is(g => g == args.RequestId),
- It.Is(r => r == (int) MessageBoxResult.No)), Times.Once);
- }
-
- [TestMethod]
- public void Communication_MustCorrectlyHandlePasswordRequest()
- {
- var args = new PasswordRequestEventArgs
- {
- Purpose = PasswordRequestPurpose.LocalSettings,
- RequestId = Guid.NewGuid()
- };
- var dialog = new Mock();
- var result = new PasswordDialogResult { Password = "blubb", Success = true };
-
- dialog.Setup(d => d.Show(It.IsAny())).Returns(result);
- uiFactory.Setup(f => f.CreatePasswordDialog(It.IsAny(), It.IsAny())).Returns(dialog.Object);
-
- sut.TryStart();
- clientHost.Raise(c => c.PasswordRequested += null, args);
-
- runtimeProxy.Verify(p => p.SubmitPassword(
- It.Is(g => g == args.RequestId),
- It.Is(b => b == result.Success),
- It.Is(s => s == result.Password)), Times.Once);
- }
-
- [TestMethod]
- public void Communication_MustCorrectlyHandleAbortedReconfiguration()
- {
- sut.TryStart();
- clientHost.Raise(c => c.ReconfigurationAborted += null);
-
- splashScreen.Verify(s => s.Hide(), Times.AtLeastOnce);
- }
-
- [TestMethod]
- public void Communication_MustInformUserAboutDeniedReconfiguration()
- {
- var args = new ReconfigurationEventArgs
- {
- ConfigurationPath = @"C:\Some\File\Path.seb"
- };
-
- sut.TryStart();
- clientHost.Raise(c => c.ReconfigurationDenied += null, args);
-
- messageBox.Verify(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny()), Times.Once);
- }
-
- [TestMethod]
- public void Communication_MustCorrectlyHandleServerCommunicationFailure()
- {
- var args = new ServerFailureActionRequestEventArgs { RequestId = Guid.NewGuid() };
- var dialog = new Mock();
-
- dialog.Setup(d => d.Show(It.IsAny())).Returns(new ServerFailureDialogResult());
- uiFactory.Setup(f => f.CreateServerFailureDialog(It.IsAny(), It.IsAny())).Returns(dialog.Object);
-
- sut.TryStart();
- clientHost.Raise(c => c.ServerFailureActionRequested += null, args);
-
- runtimeProxy.Verify(r => r.SubmitServerFailureActionResult(It.Is(g => g == args.RequestId), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once);
- uiFactory.Verify(f => f.CreateServerFailureDialog(It.IsAny(), It.IsAny()), Times.Once);
- }
-
- [TestMethod]
- public void Communication_MustCorrectlyInitiateShutdown()
- {
- sut.TryStart();
- clientHost.Raise(c => c.Shutdown += null);
-
- shutdown.Verify(s => s(), Times.Once);
- }
-
- [TestMethod]
- public void Communication_MustShutdownOnLostConnection()
- {
- sut.TryStart();
- runtimeProxy.Raise(p => p.ConnectionLost += null);
-
- messageBox.Verify(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny()), Times.Once);
- shutdown.Verify(s => s(), Times.Once);
- }
-
- [TestMethod]
- public void DisplayMonitor_MustCorrectlyHandleDisplayChangeWithTaskbar()
- {
- var boundsActionCenter = 0;
- var boundsTaskbar = 0;
- var height = 25;
- var order = 0;
- var workingArea = 0;
-
- settings.UserInterface.Taskbar.EnableTaskbar = true;
-
- actionCenter.Setup(t => t.InitializeBounds()).Callback(() => boundsActionCenter = ++order);
- displayMonitor.Setup(m => m.InitializePrimaryDisplay(It.Is(h => h == height))).Callback(() => workingArea = ++order);
- displayMonitor.Setup(m => m.ValidateConfiguration(It.IsAny())).Returns(new ValidationResult { IsAllowed = true });
- taskbar.Setup(t => t.GetAbsoluteHeight()).Returns(height);
- taskbar.Setup(t => t.InitializeBounds()).Callback(() => boundsTaskbar = ++order);
-
- sut.TryStart();
- displayMonitor.Raise(d => d.DisplayChanged += null);
-
- actionCenter.Verify(a => a.InitializeBounds(), Times.Once);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == 0)), Times.Never);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == height)), Times.Once);
- taskbar.Verify(t => t.GetAbsoluteHeight(), Times.Once);
- taskbar.Verify(t => t.InitializeBounds(), Times.Once);
-
- Assert.IsTrue(workingArea == 1);
- Assert.IsTrue(boundsActionCenter == 2);
- Assert.IsTrue(boundsTaskbar == 3);
- }
-
- [TestMethod]
- public void DisplayMonitor_MustCorrectlyHandleDisplayChangeWithoutTaskbar()
- {
- var boundsActionCenter = 0;
- var boundsTaskbar = 0;
- var height = 25;
- var order = 0;
- var workingArea = 0;
-
- settings.UserInterface.Taskbar.EnableTaskbar = false;
-
- actionCenter.Setup(t => t.InitializeBounds()).Callback(() => boundsActionCenter = ++order);
- displayMonitor.Setup(w => w.InitializePrimaryDisplay(It.Is(h => h == 0))).Callback(() => workingArea = ++order);
- displayMonitor.Setup(m => m.ValidateConfiguration(It.IsAny())).Returns(new ValidationResult { IsAllowed = true });
- taskbar.Setup(t => t.GetAbsoluteHeight()).Returns(height);
- taskbar.Setup(t => t.InitializeBounds()).Callback(() => boundsTaskbar = ++order);
-
- sut.TryStart();
- displayMonitor.Raise(d => d.DisplayChanged += null);
-
- actionCenter.Verify(a => a.InitializeBounds(), Times.Once);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == 0)), Times.Once);
- displayMonitor.Verify(d => d.InitializePrimaryDisplay(It.Is(h => h == height)), Times.Never);
- taskbar.Verify(t => t.GetAbsoluteHeight(), Times.Never);
- taskbar.Verify(t => t.InitializeBounds(), Times.Once);
-
- Assert.IsTrue(workingArea == 1);
- Assert.IsTrue(boundsActionCenter == 2);
- Assert.IsTrue(boundsTaskbar == 3);
- }
-
- [TestMethod]
- public void DisplayMonitor_MustShowLockScreenOnDisplayChange()
- {
- var lockScreen = new Mock();
-
- displayMonitor.Setup(m => m.ValidateConfiguration(It.IsAny())).Returns(new ValidationResult { IsAllowed = false });
- lockScreen.Setup(l => l.WaitForResult()).Returns(new LockScreenResult());
- uiFactory
- .Setup(f => f.CreateLockScreen(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()))
- .Returns(lockScreen.Object);
-
- sut.TryStart();
- displayMonitor.Raise(d => d.DisplayChanged += null);
-
- lockScreen.Verify(l => l.Show(), Times.Once);
- }
-
- [TestMethod]
- public void Operations_MustAskForAutomaticApplicationTermination()
- {
- var args = new ApplicationTerminationEventArgs(Enumerable.Empty());
-
- messageBox.Setup(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny())).Returns(MessageBoxResult.Yes);
-
- sut.TryStart();
- operationSequence.Raise(s => s.ActionRequired += null, args);
-
- Assert.IsTrue(args.TerminateProcesses);
- }
-
- [TestMethod]
- public void Operations_MustAbortAskingForAutomaticApplicationTermination()
- {
- var args = new ApplicationTerminationEventArgs(Enumerable.Empty());
-
- messageBox.Setup(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny())).Returns(MessageBoxResult.No);
-
- sut.TryStart();
- operationSequence.Raise(s => s.ActionRequired += null, args);
-
- Assert.IsFalse(args.TerminateProcesses);
- }
-
- [TestMethod]
- public void Operations_MustAskForApplicationPath()
- {
- var args = new ApplicationNotFoundEventArgs(default, default);
- var result = new FileSystemDialogResult { FullPath = @"C:\Some\random\path\", Success = true };
-
- fileSystemDialog.Setup(d => d.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny())).Returns(result);
- text.SetReturnsDefault(string.Empty);
-
- sut.TryStart();
- operationSequence.Raise(s => s.ActionRequired += null, args);
-
- Assert.AreEqual(result.FullPath, args.CustomPath);
- Assert.IsTrue(args.Success);
- }
-
- [TestMethod]
- public void Operations_MustAbortAskingForApplicationPath()
- {
- var args = new ApplicationNotFoundEventArgs(default, default);
- var result = new FileSystemDialogResult { Success = false };
-
- fileSystemDialog.Setup(d => d.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny())).Returns(result);
- text.SetReturnsDefault(string.Empty);
-
- sut.TryStart();
- operationSequence.Raise(s => s.ActionRequired += null, args);
-
- Assert.IsNull(args.CustomPath);
- Assert.IsFalse(args.Success);
- }
-
- [TestMethod]
- public void Operations_MustInformAboutFailedApplicationInitialization()
- {
- var args = new ApplicationInitializationFailedEventArgs(default, default, FactoryResult.NotFound);
-
- text.SetReturnsDefault(string.Empty);
- sut.TryStart();
- operationSequence.Raise(s => s.ActionRequired += null, args);
-
- messageBox.Verify(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny()), Times.Once);
- }
-
- [TestMethod]
- public void Operations_MustInformAboutFailedApplicationTermination()
- {
- var args = new ApplicationTerminationFailedEventArgs(Enumerable.Empty());
-
- text.SetReturnsDefault(string.Empty);
- sut.TryStart();
- operationSequence.Raise(s => s.ActionRequired += null, args);
-
- messageBox.Verify(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny()), Times.Once);
- }
-
- [TestMethod]
- public void Operations_MustUpdateProgress()
- {
- var args = new ProgressChangedEventArgs
- {
- CurrentValue = 23,
- IsIndeterminate = true,
- MaxValue = 150,
- Progress = true,
- Regress = true
- };
-
- sut.TryStart();
- operationSequence.Raise(o => o.ProgressChanged += null, args);
-
- splashScreen.Verify(s => s.SetValue(It.Is(i => i == args.CurrentValue)), Times.Once);
- splashScreen.Verify(s => s.SetIndeterminate(), Times.Once);
- splashScreen.Verify(s => s.SetMaxValue(It.Is(i => i == args.MaxValue)), Times.Once);
- splashScreen.Verify(s => s.Progress(), Times.Once);
- splashScreen.Verify(s => s.Regress(), Times.Once);
- }
-
- [TestMethod]
- public void Operations_MustUpdateStatus()
- {
- var key = TextKey.OperationStatus_InitializeClipboard;
-
- sut.TryStart();
- operationSequence.Raise(o => o.StatusChanged += null, key);
-
- splashScreen.Verify(s => s.UpdateStatus(It.Is(k => k == key), It.IsAny()), Times.Once);
- }
-
- [TestMethod]
- public void Reconfiguration_MustAllowIfNoQuitPasswordSet()
- {
- var args = new DownloadEventArgs();
-
- appConfig.TemporaryDirectory = @"C:\Folder\Does\Not\Exist";
- coordinator.Setup(c => c.RequestReconfigurationLock()).Returns(true);
- runtimeProxy.Setup(r => r.RequestReconfiguration(It.IsAny(), It.IsAny())).Returns(new CommunicationResult(true));
-
- sut.TryStart();
- browser.Raise(b => b.ConfigurationDownloadRequested += null, "filepath.seb", args);
- args.Callback(true, string.Empty);
-
- coordinator.Verify(c => c.RequestReconfigurationLock(), Times.Once);
- coordinator.Verify(c => c.ReleaseReconfigurationLock(), Times.Never);
- runtimeProxy.Verify(r => r.RequestReconfiguration(It.IsAny(), It.IsAny()), Times.Once);
-
- Assert.IsTrue(args.AllowDownload);
- }
-
- [TestMethod]
- public void Reconfiguration_MustNotAllowWithQuitPasswordAndNoUrl()
- {
- var args = new DownloadEventArgs();
-
- appConfig.TemporaryDirectory = @"C:\Folder\Does\Not\Exist";
- settings.Security.AllowReconfiguration = true;
- settings.Security.QuitPasswordHash = "abc123";
- runtimeProxy.Setup(r => r.RequestReconfiguration(It.IsAny(), It.IsAny())).Returns(new CommunicationResult(true));
-
- sut.TryStart();
- browser.Raise(b => b.ConfigurationDownloadRequested += null, "filepath.seb", args);
-
- coordinator.Verify(c => c.RequestReconfigurationLock(), Times.Never);
- coordinator.Verify(c => c.ReleaseReconfigurationLock(), Times.Never);
- runtimeProxy.Verify(r => r.RequestReconfiguration(It.IsAny(), It.IsAny()), Times.Never);
-
- Assert.IsFalse(args.AllowDownload);
- }
-
- [TestMethod]
- public void Reconfiguration_MustNotAllowConcurrentExecution()
- {
- var args = new DownloadEventArgs();
-
- appConfig.TemporaryDirectory = @"C:\Folder\Does\Not\Exist";
- coordinator.Setup(c => c.RequestReconfigurationLock()).Returns(false);
- runtimeProxy.Setup(r => r.RequestReconfiguration(It.IsAny(), It.IsAny())).Returns(new CommunicationResult(true));
-
- sut.TryStart();
- browser.Raise(b => b.ConfigurationDownloadRequested += null, "filepath.seb", args);
- args.Callback?.Invoke(true, string.Empty);
-
- coordinator.Verify(c => c.RequestReconfigurationLock(), Times.Once);
- coordinator.Verify(c => c.ReleaseReconfigurationLock(), Times.Never);
- runtimeProxy.Verify(r => r.RequestReconfiguration(It.IsAny(), It.IsAny()), Times.Never);
-
- Assert.IsFalse(args.AllowDownload);
- }
-
- [TestMethod]
- public void Reconfiguration_MustAllowIfUrlMatches()
- {
- var args = new DownloadEventArgs { Url = "sebs://www.somehost.org/some/path/some_configuration.seb?query=123" };
-
- appConfig.TemporaryDirectory = @"C:\Folder\Does\Not\Exist";
- coordinator.Setup(c => c.RequestReconfigurationLock()).Returns(true);
- settings.Security.AllowReconfiguration = true;
- settings.Security.QuitPasswordHash = "abc123";
- settings.Security.ReconfigurationUrl = "sebs://www.somehost.org/some/path/*.seb?query=123";
- runtimeProxy.Setup(r => r.RequestReconfiguration(It.IsAny(), It.IsAny())).Returns(new CommunicationResult(true));
-
- sut.TryStart();
- browser.Raise(b => b.ConfigurationDownloadRequested += null, "filepath.seb", args);
- args.Callback(true, string.Empty);
-
- coordinator.Verify(c => c.RequestReconfigurationLock(), Times.Once);
- coordinator.Verify(c => c.ReleaseReconfigurationLock(), Times.Never);
- runtimeProxy.Verify(r => r.RequestReconfiguration(It.IsAny(), It.IsAny()), Times.Once);
-
- Assert.IsTrue(args.AllowDownload);
- }
-
- [TestMethod]
- public void Reconfiguration_MustDenyIfNotAllowed()
- {
- var args = new DownloadEventArgs();
-
- settings.Security.AllowReconfiguration = false;
- settings.Security.QuitPasswordHash = "abc123";
-
- sut.TryStart();
- browser.Raise(b => b.ConfigurationDownloadRequested += null, "filepath.seb", args);
-
- coordinator.Verify(c => c.RequestReconfigurationLock(), Times.Never);
- coordinator.Verify(c => c.ReleaseReconfigurationLock(), Times.Never);
- runtimeProxy.Verify(r => r.RequestReconfiguration(It.IsAny(), It.IsAny()), Times.Never);
-
- Assert.IsFalse(args.AllowDownload);
- }
-
- [TestMethod]
- public void Reconfiguration_MustDenyIfUrlDoesNotMatch()
- {
- var args = new DownloadEventArgs { Url = "sebs://www.somehost.org/some/path/some_configuration.seb?query=123" };
-
- settings.Security.AllowReconfiguration = false;
- settings.Security.QuitPasswordHash = "abc123";
- settings.Security.ReconfigurationUrl = "sebs://www.somehost.org/some/path/other_configuration.seb?query=123";
-
- sut.TryStart();
- browser.Raise(b => b.ConfigurationDownloadRequested += null, "filepath.seb", args);
-
- coordinator.Verify(c => c.RequestReconfigurationLock(), Times.Never);
- coordinator.Verify(c => c.ReleaseReconfigurationLock(), Times.Never);
- runtimeProxy.Verify(r => r.RequestReconfiguration(It.IsAny(), It.IsAny()), Times.Never);
-
- Assert.IsFalse(args.AllowDownload);
- }
-
- [TestMethod]
- public void Reconfiguration_MustCorrectlyHandleDownload()
- {
- var downloadPath = @"C:\Folder\Does\Not\Exist\filepath.seb";
- var downloadUrl = @"https://www.host.abc/someresource.seb";
- var filename = "filepath.seb";
- var args = new DownloadEventArgs();
-
- appConfig.TemporaryDirectory = @"C:\Folder\Does\Not\Exist";
- coordinator.Setup(c => c.RequestReconfigurationLock()).Returns(true);
- messageBox.Setup(m => m.Show(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny())).Returns(MessageBoxResult.Yes);
- runtimeProxy.Setup(r => r.RequestReconfiguration(
- It.Is(p => p == downloadPath),
- It.Is(u => u == downloadUrl))).Returns(new CommunicationResult(true));
- settings.Security.AllowReconfiguration = true;
-
- sut.TryStart();
- browser.Raise(b => b.ConfigurationDownloadRequested += null, filename, args);
- args.Callback(true, downloadUrl, downloadPath);
-
- coordinator.Verify(c => c.RequestReconfigurationLock(), Times.Once);
- coordinator.Verify(c => c.ReleaseReconfigurationLock(), Times.Never);
- runtimeProxy.Verify(r => r.RequestReconfiguration(It.Is(p => p == downloadPath), It.Is