From 0c963a817aeb945e0d414004cc2bc454cb2fd67e Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Thu, 29 Jul 2021 01:22:14 -0400 Subject: [PATCH 1/3] ace2_inner.js: Delete unnecessary `ace_outerWin` variable --- src/static/js/ace.js | 1 - src/static/js/ace2_inner.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/static/js/ace.js b/src/static/js/ace.js index 6a1548f2e76..387576ce464 100644 --- a/src/static/js/ace.js +++ b/src/static/js/ace.js @@ -241,7 +241,6 @@ const Ace2Editor = function () { // The iframe MUST have a src or srcdoc property to avoid browser quirks. See the comment above // outerFrame.srcdoc. innerFrame.srcdoc = ''; - innerFrame.ace_outerWin = outerWindow; outerDocument.body.insertBefore(innerFrame, outerDocument.body.firstChild); const innerWindow = innerFrame.contentWindow; diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 91266f2f299..caed956c2c7 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -61,8 +61,7 @@ function Ace2Inner(editorInfo, cssManagers) { }; const iframe = window.frameElement; - const outerWin = iframe.ace_outerWin; - iframe.ace_outerWin = null; // prevent IE 6 memory leak + const outerWin = window.parent; const sideDiv = iframe.nextSibling; const lineMetricsDiv = sideDiv.nextSibling; let lineNumbersShown; From 9fda5adcefd86bfaba267d4988954bbe54ddd6c2 Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Thu, 29 Jul 2021 01:22:44 -0400 Subject: [PATCH 2/3] ace2_inner.js: Improve discovery of `sidediv` and `linemetricsdiv` The `Node.nextSibling` property returns the next Node, not the next Element. If whitespace, an HTML comment, or any other type of non-Element Node is ever introduced between the Elements then `.nextSibling` no longer returns the desired Element. Switching to `Element.nextElementSibling` would work, but finding the Elements by ID is more readable and future-proof. --- src/static/js/ace2_inner.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index caed956c2c7..32fc0a84f9d 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -60,10 +60,10 @@ function Ace2Inner(editorInfo, cssManagers) { window.focus(); }; - const iframe = window.frameElement; const outerWin = window.parent; - const sideDiv = iframe.nextSibling; - const lineMetricsDiv = sideDiv.nextSibling; + const outerDoc = outerWin.document; + const sideDiv = outerDoc.getElementById('sidediv'); + const lineMetricsDiv = outerDoc.getElementById('linemetricsdiv'); let lineNumbersShown; let sideDivInner; From e61888dfe26a94a961e013d8bbec3fe3fb2d4290 Mon Sep 17 00:00:00 2001 From: webzwo0i Date: Tue, 20 Jul 2021 18:50:18 +0200 Subject: [PATCH 3/3] ace.js: Don't use srcdoc when creating iframes (see #4975) Using srcdoc, especially with multiple nested iframes, seems to be problematic when using `self` in CSP policies. --- src/static/empty.html | 1 + src/static/js/ace.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 src/static/empty.html diff --git a/src/static/empty.html b/src/static/empty.html new file mode 100644 index 00000000000..ef02d22ca72 --- /dev/null +++ b/src/static/empty.html @@ -0,0 +1 @@ +Empty diff --git a/src/static/js/ace.js b/src/static/js/ace.js index 387576ce464..1e73ac48f83 100644 --- a/src/static/js/ace.js +++ b/src/static/js/ace.js @@ -197,7 +197,9 @@ const Ace2Editor = function () { // - Chrome never fires any events on the frame or document. Eventually the document's // readyState becomes 'complete' even though it never fires a readystatechange event. // - Safari behaves like Chrome. - outerFrame.srcdoc = ''; + // srcdoc is avoided because Firefox's Content Security Policy engine does not properly handle + // 'self' with nested srcdoc iframes: https://bugzilla.mozilla.org/show_bug.cgi?id=1721296 + outerFrame.src = '../static/empty.html'; info.frame = outerFrame; document.getElementById(containerId).appendChild(outerFrame); const outerWindow = outerFrame.contentWindow; @@ -240,7 +242,7 @@ const Ace2Editor = function () { innerFrame.allowTransparency = true; // for IE // The iframe MUST have a src or srcdoc property to avoid browser quirks. See the comment above // outerFrame.srcdoc. - innerFrame.srcdoc = ''; + innerFrame.src = 'empty.html'; outerDocument.body.insertBefore(innerFrame, outerDocument.body.firstChild); const innerWindow = innerFrame.contentWindow;