diff --git a/packages/react-dom/src/client/ReactInputSelection.js b/packages/react-dom/src/client/ReactInputSelection.js index 54ad4a937f33..f2d0987608b3 100644 --- a/packages/react-dom/src/client/ReactInputSelection.js +++ b/packages/react-dom/src/client/ReactInputSelection.js @@ -40,15 +40,29 @@ function isInDocument(node) { ); } +function isSameOriginFrame(iframe) { + try { + // Accessing the contentDocument of a HTMLIframeElement can cause the browser + // to throw, e.g. if it has a cross-origin src attribute. + // Safari will show an error in the console when the access results in "Blocked a frame with origin". e.g: + // iframe.contentDocument.defaultView; + // A safety way is to access one of the cross origin properties: Window or Location + // Which might result in "SecurityError" DOM Exception and it is compatible to Safari. + // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl + + return typeof iframe.contentWindow.location.href === 'string'; + } catch (err) { + return false; + } +} + function getActiveElementDeep() { let win = window; let element = getActiveElement(); while (element instanceof win.HTMLIFrameElement) { - // Accessing the contentDocument of a HTMLIframeElement can cause the browser - // to throw, e.g. if it has a cross-origin src attribute - try { - win = element.contentDocument.defaultView; - } catch (e) { + if (isSameOriginFrame(element)) { + win = element.contentWindow; + } else { return element; } element = getActiveElement(win.document);