[FIX] web_editor: _blank href for readonlyIframe

The "readonly iframe" mode of html_editor does not do
the processing required to ensure all links target a new tab when
the setup is called more than once.

As this happens often, links effectively did not redirect to a new tab.

Additionally sandboxedIframe did not allow new tabs to open.
We add `allow-popups` and `allow-popups-to-escape-sandbox`
to the sandbox attributes.

This is safe as the popup will not have access to the odoo window.
Which should mean it's as safe as opening a link without the sandbox.

opw-3337670

closes odoo/odoo#124395

X-original-commit: 61b6b6bf6181fe703cd3d455dba9004e1fad7135
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Thiry Renaud (reth) <reth@odoo.com>
This commit is contained in:
Renaud Thiry
2023-06-09 10:55:02 +02:00
parent c007449230
commit ef37dce5fa
3 changed files with 8 additions and 6 deletions
@@ -439,6 +439,7 @@ export class HtmlField extends Component {
if (this.iframePromise && iframeTarget) {
if (iframeTarget.innerHTML !== this.props.record.data[this.props.name]) {
iframeTarget.innerHTML = this.props.record.data[this.props.name];
retargetLinks(iframeTarget);
}
return this.iframePromise;
}
@@ -4,7 +4,8 @@
<t t-name="web_editor.HtmlField" owl="1">
<t t-if="props.readonly || props.notEditable || (sandboxedPreview and !state.showCodeView)">
<t t-if="this.showIframe">
<iframe t-ref="iframe" t-att-class="{'d-none': !this.state.iframeVisible, 'o_readonly': true}" t-att-sandbox="sandboxedPreview ? 'allow-same-origin' : false"></iframe>
<iframe t-ref="iframe" t-att-class="{'d-none': !this.state.iframeVisible, 'o_readonly': true}"
t-att-sandbox="sandboxedPreview ? 'allow-same-origin allow-popups allow-popups-to-escape-sandbox' : false"></iframe>
</t>
<t t-else="">
<div t-ref="readonlyElement" class="o_readonly" t-out="markupValue" />
@@ -72,7 +72,7 @@ QUnit.module("WebEditor.HtmlField", ({ beforeEach }) => {
</form>`,
});
assert.containsOnce(target, '.o_field_html[name="txt"] iframe[sandbox="allow-same-origin"]');
assert.containsOnce(target, '.o_field_html[name="txt"] iframe[sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"]');
});
QUnit.test("readonly sandboxed preview", async (assert) => {
@@ -107,7 +107,7 @@ QUnit.module("WebEditor.HtmlField", ({ beforeEach }) => {
</form>`,
});
const readonlyIframe = target.querySelector('.o_field_html[name="txt"] iframe[sandbox="allow-same-origin"]');
const readonlyIframe = target.querySelector('.o_field_html[name="txt"] iframe[sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"]');
assert.ok(readonlyIframe);
await iframeReady(readonlyIframe);
assert.strictEqual(readonlyIframe.contentDocument.body.innerText, 'Hello');
@@ -174,7 +174,7 @@ QUnit.module("WebEditor.HtmlField", ({ beforeEach }) => {
});
// check original displayed content
let iframe = target.querySelector('.o_field_html[name="txt"] iframe[sandbox="allow-same-origin"]');
let iframe = target.querySelector('.o_field_html[name="txt"] iframe[sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"]');
assert.ok(iframe, 'Should use a sanboxed iframe');
await iframeReady(iframe);
assert.strictEqual(iframe.contentDocument.body.textContent.trim(), 'Hello');
@@ -192,7 +192,7 @@ QUnit.module("WebEditor.HtmlField", ({ beforeEach }) => {
await click(target, '#codeview-btn-group > button');
await togglePromises[togglePromiseId];
// check dispayed content after edit
iframe = target.querySelector('.o_field_html[name="txt"] iframe[sandbox="allow-same-origin"]');
iframe = target.querySelector('.o_field_html[name="txt"] iframe[sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"]');
await iframeReady(iframe);
assert.strictEqual(iframe.contentDocument.body.textContent.trim(), 'Hi');
assert.strictEqual(iframe.contentDocument.head.querySelector('style').textContent.trim().replace(/\s/g, ''),
@@ -249,7 +249,7 @@ QUnit.module("WebEditor.HtmlField", ({ beforeEach }) => {
</form>`,
});
assert.containsOnce(target, '.o_field_html[name="txt"] iframe[sandbox="allow-same-origin"]');
assert.containsOnce(target, '.o_field_html[name="txt"] iframe[sandbox="allow-same-origin allow-popups allow-popups-to-escape-sandbox"]');
});
});