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 ( <>