From 7966c8f88fba35048799d014fcbd5802b2182abc Mon Sep 17 00:00:00 2001 From: Horatiu Muresan <39557534+horymury@users.noreply.github.com> Date: Wed, 25 Aug 2021 15:23:40 +0300 Subject: [PATCH] feat(errors) Expose errors through Iframe API (#9801) --- modules/API/API.js | 13 ++++++ modules/API/external/external_api.js | 1 + react/features/overlay/middleware.js | 69 +++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/modules/API/API.js b/modules/API/API.js index fb9d2dc6b..3a5947c1f 100644 --- a/modules/API/API.js +++ b/modules/API/API.js @@ -1325,6 +1325,19 @@ class API { }); } + /** + * Notify external application (if API is enabled) that an error occured. + * + * @param {Object} error - The error. + * @returns {void} + */ + notifyError(error: Object) { + this._sendEvent({ + name: 'error', + error + }); + } + /** * Disposes the allocated resources. * diff --git a/modules/API/external/external_api.js b/modules/API/external/external_api.js index 70476f7a3..8d12c1c81 100644 --- a/modules/API/external/external_api.js +++ b/modules/API/external/external_api.js @@ -81,6 +81,7 @@ const events = { 'device-list-changed': 'deviceListChanged', 'display-name-change': 'displayNameChange', 'email-change': 'emailChange', + 'error': 'error', 'endpoint-text-message-received': 'endpointTextMessageReceived', 'feedback-submitted': 'feedbackSubmitted', 'feedback-prompt-displayed': 'feedbackPromptDisplayed', diff --git a/react/features/overlay/middleware.js b/react/features/overlay/middleware.js index 8aab287b6..cc5f023ee 100644 --- a/react/features/overlay/middleware.js +++ b/react/features/overlay/middleware.js @@ -1,6 +1,10 @@ // @flow -import { JitsiConferenceErrors } from '../base/lib-jitsi-meet'; +import { + JitsiConferenceErrors, + isFatalJitsiConferenceError, + isFatalJitsiConnectionError +} from '../base/lib-jitsi-meet'; import { StateListenerRegistry } from '../base/redux'; import { setFatalError } from './actions'; @@ -16,6 +20,47 @@ const NON_OVERLAY_ERRORS = [ JitsiConferenceErrors.CONNECTION_ERROR ]; +const ERROR_TYPES = { + CONFIG: 'CONFIG', + CONNECTION: 'CONNECTION', + CONFERENCE: 'CONFERENCE' +}; + +/** + * Gets the error type and whether it's fatal or not. + * + * @param {Function} getState - The redux function for fetching the current state. + * @param {Object|string} error - The error to process. + * @returns {void} + */ +const getErrorExtraInfo = (getState, error) => { + const state = getState(); + const { error: conferenceError } = state['features/base/conference']; + const { error: configError } = state['features/base/config']; + const { error: connectionError } = state['features/base/connection']; + + if (error === conferenceError) { + return { + type: ERROR_TYPES.CONFERENCE, + isFatal: isFatalJitsiConferenceError(error.name || error) + }; + } + + if (error === configError) { + return { + type: ERROR_TYPES.CONFIG, + isFatal: true + }; + } + + if (error === connectionError) { + return { + type: ERROR_TYPES.CONNECTION, + isFatal: isFatalJitsiConnectionError(error.name || error) + }; + } +}; + /** * State listener which emits the {@code fatalErrorOccurred} action which works * as a catch all for critical errors which have not been claimed by any other @@ -29,10 +74,22 @@ StateListenerRegistry.register( return configError || connectionError || conferenceError; }, - /* listener */ (error, { dispatch }) => { - error - && NON_OVERLAY_ERRORS.indexOf(error.name) === -1 - && typeof error.recoverable === 'undefined' - && dispatch(setFatalError(error)); + /* listener */ (error, { dispatch, getState }) => { + if (!error) { + return; + } + + if (typeof APP !== 'undefined') { + const parsedError = typeof error === 'string' ? { name: error } : error; + + APP.API.notifyError({ + ...parsedError, + ...getErrorExtraInfo(getState, error) + }); + } + + if (NON_OVERLAY_ERRORS.indexOf(error.name) === -1 && typeof error.recoverable === 'undefined') { + dispatch(setFatalError(error)); + } } );