Files
frontend-app-profile/plugins/PluginContainerIframe.jsx
Jason Wesson bd8221997e Move changes from ProfilePluginPOC to aperture/PluginPOCFeature (#883)
* build: create profile plugin page
* build: add plugins folder to Profile
* build: wrap Profile Plugin Page with Plugin

Co-authored-by: Jason Wesson <jwesson@2u.com>
2023-10-18 11:43:43 -07:00

100 lines
2.5 KiB
JavaScript

import React, {
useEffect, useState,
} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {
PLUGIN_MOUNTED,
PLUGIN_READY,
PLUGIN_RESIZE,
} from './data/constants';
import {
dispatchPluginEvent,
useElementSize,
usePluginEvent,
} from './data/hooks';
import { pluginConfigShape } from './data/shapes';
/**
* Feature policy for iframe, allowing access to certain courseware-related media.
*
* We must use the wildcard (*) origin for each feature, as courseware content
* may be embedded in external iframes. Notably, xblock-lti-consumer is a popular
* block that iframes external course content.
* This policy was selected in conference with the edX Security Working Group.
* Changes to it should be vetted by them (security@edx.org).
*/
export const IFRAME_FEATURE_POLICY = (
'fullscreen; microphone *; camera *; midi *; geolocation *; encrypted-media *'
);
// eslint-disable-next-line react/function-component-definition
export default function PluginContainerIframe({
config, fallback, className, ...props
}) {
const { url } = config;
const { title, scrolling } = props;
const [mounted, setMounted] = useState(false);
const [ready, setReady] = useState(false);
const [iframeRef, iframeElement, width, height] = useElementSize();
useEffect(() => {
if (mounted) {
dispatchPluginEvent(iframeElement, {
type: PLUGIN_RESIZE,
payload: {
width,
height,
},
}, url);
}
}, [iframeElement, mounted, width, height, url]);
usePluginEvent(iframeElement, PLUGIN_MOUNTED, () => {
setMounted(true);
});
usePluginEvent(iframeElement, PLUGIN_READY, () => {
setReady(true);
});
return (
<>
<iframe
ref={iframeRef}
title={title}
src={url}
allow={IFRAME_FEATURE_POLICY}
scrolling={scrolling}
referrerPolicy="origin" // The sent referrer will be limited to the origin of the referring page: its scheme, host, and port.
className={classNames(
'border border-0',
{ 'd-none': !ready },
className,
)}
{...props}
/>
{!ready && fallback}
</>
);
}
PluginContainerIframe.propTypes = {
config: pluginConfigShape,
fallback: PropTypes.node,
scrolling: PropTypes.oneOf(['auto', 'yes', 'no']),
title: PropTypes.string,
className: PropTypes.string,
};
PluginContainerIframe.defaultProps = {
config: null,
fallback: null,
scrolling: 'auto',
title: null,
className: null,
};