SEBWIN-449: Implemented basic functionality of Jitsi Meet.
This commit is contained in:
		
							parent
							
								
									e72456b79e
								
							
						
					
					
						commit
						52217fa477
					
				
					 13 changed files with 358 additions and 113 deletions
				
			
		| 
						 | 
				
			
			@ -249,7 +249,7 @@ namespace SafeExamBrowser.Client
 | 
			
		|||
 | 
			
		||||
		private IOperation BuildProctoringOperation()
 | 
			
		||||
		{
 | 
			
		||||
			var controller = new ProctoringController(uiFactory);
 | 
			
		||||
			var controller = new ProctoringController(ModuleLogger(nameof(ProctoringController)), uiFactory);
 | 
			
		||||
			var operation = new ProctoringOperation(context, logger, controller);
 | 
			
		||||
 | 
			
		||||
			context.ProctoringController = controller;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,50 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
 | 
			
		|||
		{
 | 
			
		||||
			switch (key)
 | 
			
		||||
			{
 | 
			
		||||
				// TODO
 | 
			
		||||
				case Keys.Proctoring.JitsiMeet.RoomName:
 | 
			
		||||
					MapJitsiMeetRoomName(settings, value);
 | 
			
		||||
					break;
 | 
			
		||||
				case Keys.Proctoring.JitsiMeet.ServerUrl:
 | 
			
		||||
					MapJitsiMeetServerUrl(settings, value);
 | 
			
		||||
					break;
 | 
			
		||||
				case Keys.Proctoring.JitsiMeet.Subject:
 | 
			
		||||
					MapJitsiMeetSubject(settings, value);
 | 
			
		||||
					break;
 | 
			
		||||
				case Keys.Proctoring.JitsiMeet.Token:
 | 
			
		||||
					MapJitsiMeetToken(settings, value);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void MapJitsiMeetRoomName(AppSettings settings, object value)
 | 
			
		||||
		{
 | 
			
		||||
			if (value is string name)
 | 
			
		||||
			{
 | 
			
		||||
				settings.Proctoring.JitsiMeet.RoomName = name;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void MapJitsiMeetServerUrl(AppSettings settings, object value)
 | 
			
		||||
		{
 | 
			
		||||
			if (value is string url)
 | 
			
		||||
			{
 | 
			
		||||
				settings.Proctoring.JitsiMeet.ServerUrl = url;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void MapJitsiMeetSubject(AppSettings settings, object value)
 | 
			
		||||
		{
 | 
			
		||||
			if (value is string subject)
 | 
			
		||||
			{
 | 
			
		||||
				settings.Proctoring.JitsiMeet.Subject = subject;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void MapJitsiMeetToken(AppSettings settings, object value)
 | 
			
		||||
		{
 | 
			
		||||
			if (value is string token)
 | 
			
		||||
			{
 | 
			
		||||
				settings.Proctoring.JitsiMeet.Token = token;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -219,6 +219,10 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
 | 
			
		|||
			internal static class JitsiMeet
 | 
			
		||||
			{
 | 
			
		||||
				internal const string Enabled = "jitsiMeetEnable";
 | 
			
		||||
				internal const string RoomName = "jitsiMeetRoom";
 | 
			
		||||
				internal const string ServerUrl = "jitsiMeetServerURL";
 | 
			
		||||
				internal const string Subject = "jitsiMeetSubject";
 | 
			
		||||
				internal const string Token = "jitsiMeetToken";
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			internal static class Zoom
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								SafeExamBrowser.Proctoring/JitsiMeet/index.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								SafeExamBrowser.Proctoring/JitsiMeet/index.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="utf-8" />
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <div id="placeholder" />
 | 
			
		||||
        <script src='https://meet.jit.si/external_api.js'></script>
 | 
			
		||||
        <script type="text/javascript">
 | 
			
		||||
            var domain = "%%_DOMAIN_%%";
 | 
			
		||||
            var options = {
 | 
			
		||||
                height: "100%",
 | 
			
		||||
                jwt: "%%_TOKEN_%%",
 | 
			
		||||
                parentNode: document.querySelector('#placeholder'),
 | 
			
		||||
                roomName: "%%_ROOM_NAME_%%",
 | 
			
		||||
                width: "100%"
 | 
			
		||||
            };
 | 
			
		||||
            var api = new JitsiMeetExternalAPI(domain, options);
 | 
			
		||||
 | 
			
		||||
            api.executeCommand("subject", "%%_SUBJECT_%%");
 | 
			
		||||
        </script>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -6,17 +6,46 @@
 | 
			
		|||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using Microsoft.Web.WebView2.Core;
 | 
			
		||||
using Microsoft.Web.WebView2.Wpf;
 | 
			
		||||
using SafeExamBrowser.Logging.Contracts;
 | 
			
		||||
using SafeExamBrowser.UserInterface.Contracts.Proctoring;
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Proctoring
 | 
			
		||||
{
 | 
			
		||||
	internal class ProctoringControl : WebView2, IProctoringControl
 | 
			
		||||
	{
 | 
			
		||||
		internal ProctoringControl()
 | 
			
		||||
		private readonly ILogger logger;
 | 
			
		||||
 | 
			
		||||
		internal ProctoringControl(ILogger logger)
 | 
			
		||||
		{
 | 
			
		||||
			Source = new Uri("https://www.microsoft.com");
 | 
			
		||||
			this.logger = logger;
 | 
			
		||||
			CoreWebView2InitializationCompleted += ProctoringControl_CoreWebView2InitializationCompleted;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void CoreWebView2_PermissionRequested(object sender, CoreWebView2PermissionRequestedEventArgs e)
 | 
			
		||||
		{
 | 
			
		||||
			if (e.PermissionKind == CoreWebView2PermissionKind.Camera || e.PermissionKind == CoreWebView2PermissionKind.Microphone)
 | 
			
		||||
			{
 | 
			
		||||
				logger.Info($"Granted access to {e.PermissionKind}.");
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				logger.Info($"Denied access to {e.PermissionKind}.");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void ProctoringControl_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
 | 
			
		||||
		{
 | 
			
		||||
			if (e.IsSuccess)
 | 
			
		||||
			{
 | 
			
		||||
				CoreWebView2.PermissionRequested += CoreWebView2_PermissionRequested;
 | 
			
		||||
				logger.Info("Successfully initialized.");
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				logger.Error("Failed to initialize!", e.InitializationException);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,10 @@
 | 
			
		|||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using SafeExamBrowser.Logging.Contracts;
 | 
			
		||||
using SafeExamBrowser.Proctoring.Contracts;
 | 
			
		||||
using SafeExamBrowser.Settings.Proctoring;
 | 
			
		||||
using SafeExamBrowser.UserInterface.Contracts;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,31 +19,72 @@ namespace SafeExamBrowser.Proctoring
 | 
			
		|||
{
 | 
			
		||||
	public class ProctoringController : IProctoringController
 | 
			
		||||
	{
 | 
			
		||||
		private readonly IModuleLogger logger;
 | 
			
		||||
		private readonly IUserInterfaceFactory uiFactory;
 | 
			
		||||
 | 
			
		||||
		private IProctoringWindow window;
 | 
			
		||||
 | 
			
		||||
		public ProctoringController(IUserInterfaceFactory uiFactory)
 | 
			
		||||
		public ProctoringController(IModuleLogger logger, IUserInterfaceFactory uiFactory)
 | 
			
		||||
		{
 | 
			
		||||
			this.logger = logger;
 | 
			
		||||
			this.uiFactory = uiFactory;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Initialize(ProctoringSettings settings)
 | 
			
		||||
		{
 | 
			
		||||
			var control = new ProctoringControl();
 | 
			
		||||
			if (settings.JitsiMeet.Enabled || settings.Zoom.Enabled)
 | 
			
		||||
			{
 | 
			
		||||
				var control = new ProctoringControl(logger.CloneFor(nameof(ProctoringControl)));
 | 
			
		||||
 | 
			
		||||
				control.EnsureCoreWebView2Async().ContinueWith(_ =>
 | 
			
		||||
				{
 | 
			
		||||
					control.Dispatcher.Invoke(() => control.NavigateToString(LoadContent(settings)));
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				window = uiFactory.CreateProctoringWindow(control);
 | 
			
		||||
				window.Show();
 | 
			
		||||
 | 
			
		||||
			// TODO
 | 
			
		||||
			//var content = load Zoom page, replace //INDEX_JS//;
 | 
			
		||||
 | 
			
		||||
			//control.NavigateToString(content);
 | 
			
		||||
				logger.Info($"Initialized proctoring with {(settings.JitsiMeet.Enabled ? "Jitsi Meet" : "Zoom")}.");
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				logger.Warn("Failed to initialize remote proctoring because no provider is enabled in the active configuration.");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Terminate()
 | 
			
		||||
		{
 | 
			
		||||
			window?.Close();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private string LoadContent(ProctoringSettings settings)
 | 
			
		||||
		{
 | 
			
		||||
			var provider = settings.JitsiMeet.Enabled ? "JitsiMeet" : "Zoom";
 | 
			
		||||
			var assembly = Assembly.GetAssembly(typeof(ProctoringController));
 | 
			
		||||
			var path = $"{typeof(ProctoringController).Namespace}.{provider}.index.html";
 | 
			
		||||
 | 
			
		||||
			using (var stream = assembly.GetManifestResourceStream(path))
 | 
			
		||||
			using (var reader = new StreamReader(stream))
 | 
			
		||||
			{
 | 
			
		||||
				var html = reader.ReadToEnd();
 | 
			
		||||
 | 
			
		||||
				if (settings.JitsiMeet.Enabled)
 | 
			
		||||
				{
 | 
			
		||||
					html = html.Replace("%%_DOMAIN_%%", settings.JitsiMeet.ServerUrl);
 | 
			
		||||
					html = html.Replace("%%_ROOM_NAME_%%", settings.JitsiMeet.RoomName);
 | 
			
		||||
					html = html.Replace("%%_SUBJECT_%%", settings.JitsiMeet.Subject);
 | 
			
		||||
					html = html.Replace("%%_TOKEN_%%", settings.JitsiMeet.Token);
 | 
			
		||||
				}
 | 
			
		||||
				else if (settings.Zoom.Enabled)
 | 
			
		||||
				{
 | 
			
		||||
					html = html.Replace("%%_API_KEY_%%", settings.Zoom.ApiKey);
 | 
			
		||||
					html = html.Replace("%%_API_SECRET_%%", settings.Zoom.ApiSecret);
 | 
			
		||||
					html = html.Replace("123456789", Convert.ToString(settings.Zoom.MeetingNumber));
 | 
			
		||||
					html = html.Replace("%%_USER_NAME_%%", settings.Zoom.UserName);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return html;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,12 +95,10 @@
 | 
			
		|||
    <None Include="packages.config" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Content Include="Zoom\index.html" />
 | 
			
		||||
    <Content Include="Zoom\index.js" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="Jitsi\" />
 | 
			
		||||
    <EmbeddedResource Include="JitsiMeet\index.html" />
 | 
			
		||||
    <EmbeddedResource Include="Zoom\index.html" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup />
 | 
			
		||||
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
			
		||||
  <Import Project="..\packages\Microsoft.Web.WebView2.1.0.705.50\build\Microsoft.Web.WebView2.targets" Condition="Exists('..\packages\Microsoft.Web.WebView2.1.0.705.50\build\Microsoft.Web.WebView2.targets')" />
 | 
			
		||||
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,100 @@
 | 
			
		|||
        <script src="https://source.zoom.us/zoom-meeting-1.8.1.min.js"></script>
 | 
			
		||||
        <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9/crypto-js.min.js"></script>
 | 
			
		||||
        <script type="text/javascript">
 | 
			
		||||
            //INDEX_JS//
 | 
			
		||||
            const API_KEY = "%%_API_KEY_%%";
 | 
			
		||||
            const API_SECRET = "%%_API_SECRET_%%";
 | 
			
		||||
 | 
			
		||||
            console.log("Checking system requirements...");
 | 
			
		||||
            console.log(JSON.stringify(ZoomMtg.checkSystemRequirements()));
 | 
			
		||||
 | 
			
		||||
            console.log("Initializing Zoom...");
 | 
			
		||||
            ZoomMtg.setZoomJSLib('https://source.zoom.us/1.8.1/lib', '/av');
 | 
			
		||||
            ZoomMtg.preLoadWasm();
 | 
			
		||||
            ZoomMtg.prepareJssdk();
 | 
			
		||||
 | 
			
		||||
            const config = {
 | 
			
		||||
                meetingNumber: 123456789,
 | 
			
		||||
                leaveUrl: 'https://google.ch',
 | 
			
		||||
                userName: '%%_USER_NAME_%%',
 | 
			
		||||
                /* passWord: 'password', // if required */
 | 
			
		||||
                role: 0 // 1 for host; 0 for attendee
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            const signature = ZoomMtg.generateSignature({
 | 
			
		||||
                meetingNumber: config.meetingNumber,
 | 
			
		||||
                apiKey: API_KEY,
 | 
			
		||||
                apiSecret: API_SECRET,
 | 
			
		||||
                role: config.role,
 | 
			
		||||
                error: function (res) {
 | 
			
		||||
                    console.error("FAILED TO GENERATE SIGNATURE: " + res)
 | 
			
		||||
                },
 | 
			
		||||
                success: function (res) {
 | 
			
		||||
                    console.log("Successfully generated signature.");
 | 
			
		||||
                    console.log(res.result);
 | 
			
		||||
                },
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            console.log("Initializing meeting...");
 | 
			
		||||
 | 
			
		||||
            // See documentation: https://zoom.github.io/sample-app-web/ZoomMtg.html#init
 | 
			
		||||
            ZoomMtg.init({
 | 
			
		||||
                debug: true, //optional
 | 
			
		||||
                leaveUrl: config.leaveUrl, //required
 | 
			
		||||
                // webEndpoint: 'PSO web domain', // PSO option
 | 
			
		||||
                showMeetingHeader: true, //option
 | 
			
		||||
                disableInvite: false, //optional
 | 
			
		||||
                disableCallOut: false, //optional
 | 
			
		||||
                disableRecord: false, //optional
 | 
			
		||||
                disableJoinAudio: false, //optional
 | 
			
		||||
                audioPanelAlwaysOpen: true, //optional
 | 
			
		||||
                showPureSharingContent: false, //optional
 | 
			
		||||
                isSupportAV: true, //optional,
 | 
			
		||||
                isSupportChat: false, //optional,
 | 
			
		||||
                isSupportQA: true, //optional,
 | 
			
		||||
                isSupportCC: true, //optional,
 | 
			
		||||
                screenShare: true, //optional,
 | 
			
		||||
                rwcBackup: '', //optional,
 | 
			
		||||
                videoDrag: true, //optional,
 | 
			
		||||
                sharingMode: 'both', //optional,
 | 
			
		||||
                videoHeader: true, //optional,
 | 
			
		||||
                isLockBottom: true, // optional,
 | 
			
		||||
                isSupportNonverbal: true, // optional,
 | 
			
		||||
                isShowJoiningErrorDialog: true, // optional,
 | 
			
		||||
                inviteUrlFormat: '', // optional
 | 
			
		||||
                loginWindow: {  // optional,
 | 
			
		||||
                    width: 400,
 | 
			
		||||
                    height: 380
 | 
			
		||||
                },
 | 
			
		||||
                // meetingInfo: [ // optional
 | 
			
		||||
                //   'topic',
 | 
			
		||||
                //   'host',
 | 
			
		||||
                //   'mn',
 | 
			
		||||
                //   'pwd',
 | 
			
		||||
                //   'telPwd',
 | 
			
		||||
                //   'invite',
 | 
			
		||||
                //   'participant',
 | 
			
		||||
                //   'dc'
 | 
			
		||||
                // ],
 | 
			
		||||
                disableVoIP: false, // optional
 | 
			
		||||
                disableReport: false, // optional
 | 
			
		||||
                error: function (res) {
 | 
			
		||||
                    console.warn("INIT ERROR")
 | 
			
		||||
                    console.log(res)
 | 
			
		||||
                },
 | 
			
		||||
                success: function () {
 | 
			
		||||
                    ZoomMtg.join({
 | 
			
		||||
                        signature: signature,
 | 
			
		||||
                        apiKey: API_KEY,
 | 
			
		||||
                        meetingNumber: config.meetingNumber,
 | 
			
		||||
                        userName: config.userName,
 | 
			
		||||
                        /* passWord: meetConfig.passWord, */
 | 
			
		||||
                        error(res) {
 | 
			
		||||
                            console.warn("JOIN ERROR")
 | 
			
		||||
                            console.log(res)
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        </script>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,95 +0,0 @@
 | 
			
		|||
const API_KEY = "...";
 | 
			
		||||
const API_SECRET = "...";
 | 
			
		||||
 | 
			
		||||
console.log("Checking system requirements...");
 | 
			
		||||
console.log(JSON.stringify(ZoomMtg.checkSystemRequirements()));
 | 
			
		||||
 | 
			
		||||
console.log("Initializing Zoom...");
 | 
			
		||||
ZoomMtg.setZoomJSLib('https://source.zoom.us/1.8.1/lib', '/av');
 | 
			
		||||
ZoomMtg.preLoadWasm();
 | 
			
		||||
ZoomMtg.prepareJssdk();
 | 
			
		||||
 | 
			
		||||
const config = {
 | 
			
		||||
    meetingNumber: 123456,
 | 
			
		||||
    leaveUrl: 'https://google.ch',
 | 
			
		||||
    userName: 'Firstname Lastname',
 | 
			
		||||
    userEmail: 'firstname.lastname@yoursite.com',
 | 
			
		||||
    /* passWord: 'password', // if required */
 | 
			
		||||
    role: 0 // 1 for host; 0 for attendee
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const signature = ZoomMtg.generateSignature({
 | 
			
		||||
    meetingNumber: config.meetingNumber,
 | 
			
		||||
    apiKey: API_KEY,
 | 
			
		||||
    apiSecret: API_SECRET,
 | 
			
		||||
    role: config.role,
 | 
			
		||||
    error: function (res) {
 | 
			
		||||
        console.error("FAILED TO GENERATE SIGNATURE: " + res)
 | 
			
		||||
    },
 | 
			
		||||
    success: function (res) {
 | 
			
		||||
        console.log("Successfully generated signature.");
 | 
			
		||||
        console.log(res.result);
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
console.log("Initializing meeting...");
 | 
			
		||||
 | 
			
		||||
// See documentation: https://zoom.github.io/sample-app-web/ZoomMtg.html#init
 | 
			
		||||
ZoomMtg.init({
 | 
			
		||||
    debug: true, //optional
 | 
			
		||||
    leaveUrl: config.leaveUrl, //required
 | 
			
		||||
    // webEndpoint: 'PSO web domain', // PSO option
 | 
			
		||||
    showMeetingHeader: true, //option
 | 
			
		||||
    disableInvite: false, //optional
 | 
			
		||||
    disableCallOut: false, //optional
 | 
			
		||||
    disableRecord: false, //optional
 | 
			
		||||
    disableJoinAudio: false, //optional
 | 
			
		||||
    audioPanelAlwaysOpen: true, //optional
 | 
			
		||||
    showPureSharingContent: false, //optional
 | 
			
		||||
    isSupportAV: true, //optional,
 | 
			
		||||
    isSupportChat: false, //optional,
 | 
			
		||||
    isSupportQA: true, //optional,
 | 
			
		||||
    isSupportCC: true, //optional,
 | 
			
		||||
    screenShare: true, //optional,
 | 
			
		||||
    rwcBackup: '', //optional,
 | 
			
		||||
    videoDrag: true, //optional,
 | 
			
		||||
    sharingMode: 'both', //optional,
 | 
			
		||||
    videoHeader: true, //optional,
 | 
			
		||||
    isLockBottom: true, // optional,
 | 
			
		||||
    isSupportNonverbal: true, // optional,
 | 
			
		||||
    isShowJoiningErrorDialog: true, // optional,
 | 
			
		||||
    inviteUrlFormat: '', // optional
 | 
			
		||||
    loginWindow: {  // optional,
 | 
			
		||||
      width: 400,
 | 
			
		||||
      height: 380
 | 
			
		||||
    },
 | 
			
		||||
    // meetingInfo: [ // optional
 | 
			
		||||
    //   'topic',
 | 
			
		||||
    //   'host',
 | 
			
		||||
    //   'mn',
 | 
			
		||||
    //   'pwd',
 | 
			
		||||
    //   'telPwd',
 | 
			
		||||
    //   'invite',
 | 
			
		||||
    //   'participant',
 | 
			
		||||
    //   'dc'
 | 
			
		||||
    // ],
 | 
			
		||||
    disableVoIP: false, // optional
 | 
			
		||||
    disableReport: false, // optional
 | 
			
		||||
    error: function(res) {
 | 
			
		||||
        console.warn("INIT ERROR")
 | 
			
		||||
        console.log(res)
 | 
			
		||||
    },
 | 
			
		||||
    success: function() {
 | 
			
		||||
        ZoomMtg.join({
 | 
			
		||||
            signature: signature,
 | 
			
		||||
            apiKey: API_KEY,
 | 
			
		||||
            meetingNumber: config.meetingNumber,
 | 
			
		||||
            userName: config.userName,
 | 
			
		||||
            /* passWord: meetConfig.passWord, */
 | 
			
		||||
            error(res) {
 | 
			
		||||
                console.warn("JOIN ERROR")
 | 
			
		||||
                console.log(res)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										44
									
								
								SafeExamBrowser.Settings/Proctoring/JitsiMeetSettings.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								SafeExamBrowser.Settings/Proctoring/JitsiMeetSettings.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET)
 | 
			
		||||
 * 
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
			
		||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Settings.Proctoring
 | 
			
		||||
{
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// All settings for the meeting provider Jitsi Meet.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	[Serializable]
 | 
			
		||||
	public class JitsiMeetSettings
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Determines whether proctoring with Jitsi Meet is enabled.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public bool Enabled { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The name of the meeting room.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public string RoomName { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The URL of the Jitsi Meet server.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public string ServerUrl { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The subject of the meeting.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public string Subject { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The authentication token for the meeting.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public string Token { get; set; }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -20,5 +20,21 @@ namespace SafeExamBrowser.Settings.Proctoring
 | 
			
		|||
		/// Determines whether the entire remote proctoring feature is enabled.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public bool Enabled { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// All settings for remote proctoring with Jitsi Meet.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public JitsiMeetSettings JitsiMeet { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// All settings for remote proctoring with Zoom.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public ZoomSettings Zoom { get; set; }
 | 
			
		||||
 | 
			
		||||
		public ProctoringSettings()
 | 
			
		||||
		{
 | 
			
		||||
			JitsiMeet = new JitsiMeetSettings();
 | 
			
		||||
			Zoom = new ZoomSettings();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										44
									
								
								SafeExamBrowser.Settings/Proctoring/ZoomSettings.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								SafeExamBrowser.Settings/Proctoring/ZoomSettings.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2021 ETH Zürich, Educational Development and Technology (LET)
 | 
			
		||||
 * 
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
			
		||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace SafeExamBrowser.Settings.Proctoring
 | 
			
		||||
{
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// All settings for the meeting provider Zoom.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	[Serializable]
 | 
			
		||||
	public class ZoomSettings
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The API key to be used for authentication.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public string ApiKey { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The API secret to be used for authentication.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public string ApiSecret { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Determines whether proctoring with Zoom is enabled.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public bool Enabled { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The number of the meeting.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public int MeetingNumber { get; set; }
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The user name to be used for the meeting.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public string UserName { get; set; }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +71,9 @@
 | 
			
		|||
    <Compile Include="Browser\Proxy\ProxyProtocol.cs" />
 | 
			
		||||
    <Compile Include="Browser\Proxy\ProxyConfiguration.cs" />
 | 
			
		||||
    <Compile Include="ConfigurationMode.cs" />
 | 
			
		||||
    <Compile Include="Proctoring\JitsiMeetSettings.cs" />
 | 
			
		||||
    <Compile Include="Proctoring\ProctoringSettings.cs" />
 | 
			
		||||
    <Compile Include="Proctoring\ZoomSettings.cs" />
 | 
			
		||||
    <Compile Include="SessionMode.cs" />
 | 
			
		||||
    <Compile Include="Security\KioskMode.cs" />
 | 
			
		||||
    <Compile Include="Logging\LogLevel.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue