From a77230ae362262b2b6564137e7e2160cdef4e22e Mon Sep 17 00:00:00 2001 From: renanvalentin Date: Thu, 14 Mar 2019 17:43:16 +0100 Subject: [PATCH] fix(react-dom): check if iframe belongs to the same origin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accessing the contentDocument of a HTMLIframeElement can cause the browser to throw, e.g. if it has a cross-origin src attribute. Safari will throw an uncatchable error when the access results in "Blocked a frame with origin". e.g: ```javascript try { $0.contentDocument.defaultView } catch (err) { console.log('err', err) } > Blocked a frame with origin X from accessing a frame with origin Y. Protocols, domains, and ports must match. > err – TypeError: null is not an object (evaluating '$0.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. ```javascript try { $0.contentWindow.location.href } catch (err) { console.log('err', err) } > err – SecurityError: Blocked a frame with origin "http://localhost:3001" from accessing a cross-origin frame. Protocols, domains, and ports must match. ``` https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl --- .../src/client/ReactInputSelection.js | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/react-dom/src/client/ReactInputSelection.js b/packages/react-dom/src/client/ReactInputSelection.js index abaaa38dd2c5f7..f8a78ca9901b86 100644 --- a/packages/react-dom/src/client/ReactInputSelection.js +++ b/packages/react-dom/src/client/ReactInputSelection.js @@ -40,15 +40,30 @@ 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 throw an uncatchable error 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 + + const canReadHrefAttribute = iframe.contentWindow.location.href; + return canReadHrefAttribute != null; + } catch (err) { + return false; + } +} + function getActiveElementDeep() { let win = window; let element = getActiveElement(); while (element instanceof win.HTMLIFrameElement) { - // Accessing the contentWindow of a HTMLIframeElement can cause the browser - // to throw, e.g. if it has a cross-origin src attribute - try { + if (isSameOriginFrame(element)) { win = element.contentWindow; - } catch (e) { + } else { return element; } element = getActiveElement(win.document);