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 6a1548f2e76..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,8 +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.ace_outerWin = outerWindow;
+ innerFrame.src = 'empty.html';
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..32fc0a84f9d 100644
--- a/src/static/js/ace2_inner.js
+++ b/src/static/js/ace2_inner.js
@@ -60,11 +60,10 @@ function Ace2Inner(editorInfo, cssManagers) {
window.focus();
};
- const iframe = window.frameElement;
- const outerWin = iframe.ace_outerWin;
- iframe.ace_outerWin = null; // prevent IE 6 memory leak
- const sideDiv = iframe.nextSibling;
- const lineMetricsDiv = sideDiv.nextSibling;
+ const outerWin = window.parent;
+ const outerDoc = outerWin.document;
+ const sideDiv = outerDoc.getElementById('sidediv');
+ const lineMetricsDiv = outerDoc.getElementById('linemetricsdiv');
let lineNumbersShown;
let sideDivInner;