[FIX] website: avoid infinite redirects in iframe on Chrome
If you have the backend in a language A but the website in English only,
you can:
1) modify a record's (event, product...) name in language A (say "New
Name").
2) visit the page `/new-name-11` => the server will redirect you to the
English page `/origin-11`, with the only slug that actually exists on
the website. Chrome caches the redirection.
3) give the same name in English as in language A, try to visit
=> the server now wants to access `/new-name-11`
=> Chrome uses the cache to redirect `/new-name-11` to `/origin-11`,
=> the server tries to redirect to `/new-name-11`
=> infinite loop, Chrome puts an end to it after ± 20 redirects.
In effect, Chrome injects a "Too many redirects" layout inside the
iframe, which in turn raises a CORS error when the app tries to update
it.
At the time of this commit, the flow described here should be expected
of users, because the translation UI in the backend is not clear: the
default field displayed is in language A even though the website does
not use it, and the way to update translations is not obvious (you have
to click on the language tag, which doesn't look like a button).
Another way to artificially reproduce the issue would be:
- Create a website.redirect from /dog to /cat
- Same from /cat to /dog
- Go to /@/dog
After this commit, if we detect that behavior, we reload the iframe with
a new query parameter, making the URL brand-new (and not cached) for
Chrome.
opw-3479651
closes odoo/odoo#145306
X-original-commit: 16d47ddf128f31f13e8d0d74597635faf7f9702a
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Robin Lejeune (role) <role@odoo.com>
This commit is contained in:
committed by
Romain Derie
parent
1be5133e74
commit
41bc480b7b
@@ -353,7 +353,44 @@ export class WebsitePreview extends Component {
|
||||
this.title.setParts({ action: currentTitle });
|
||||
}
|
||||
|
||||
_onPageLoaded() {
|
||||
_onPageLoaded(ev) {
|
||||
// FIX Chrome-only. If you have the backend in a language A but the
|
||||
// website in English only, you can 1) modify a record's (event,
|
||||
// product...) name in language A (say "New Name").
|
||||
// 2) visit the page `/new-name-11` => the server will redirect you to
|
||||
// the English page `/origin-11`, which is the only one existing.
|
||||
// Chrome caches the redirection.
|
||||
// 3) give the same name in English as in language A, try to visit
|
||||
// => the server now wants to access `/new-name-11`
|
||||
// => Chrome uses the cache to redirect `/new-name-11` to `/origin-11`,
|
||||
// => the server tries to redirect to `/new-name-11` => loop.
|
||||
// Chrome injects a "Too many redirects" layout in the iframe, which in
|
||||
// turn raises a CORS error when the app tries to update the iframe.
|
||||
// If we detect that behavior, we reload the iframe with a new query
|
||||
// parameter, so that it's not cached for Chrome.
|
||||
if (
|
||||
navigator.userAgent.toLowerCase().includes("chrome")
|
||||
&& !this.iframe.el.src.includes("iframe_reload")
|
||||
) {
|
||||
try {
|
||||
/* eslint-disable no-unused-expressions */
|
||||
this.iframe.el.contentWindow.location.href;
|
||||
} catch (err) {
|
||||
if (err.name === "SecurityError") {
|
||||
ev.stopImmediatePropagation();
|
||||
// Note that iframe's `src` is the URL used to start the
|
||||
// website preview, it's not sync'd with iframe navigation.
|
||||
const srcUrl = new URL(this.iframe.el.src);
|
||||
const pathUrl = new URL(srcUrl.searchParams.get("path"), srcUrl.origin);
|
||||
pathUrl.searchParams.set("iframe_reload", "1");
|
||||
srcUrl.searchParams.set("path", `${pathUrl.pathname}${pathUrl.search}`);
|
||||
// We could inject `pathUrl` directly but keep the same
|
||||
// expected URL format `/website/force/1?path=..`
|
||||
this.iframe.el.src = srcUrl.toString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.lastHiddenPageURL !== this.iframe.el.contentWindow.location.href) {
|
||||
// Hide Ace Editor when moving to another page.
|
||||
this.websiteService.context.showResourceEditor = false;
|
||||
|
||||
Reference in New Issue
Block a user