diff --git a/addons/website/static/src/client_actions/website_preview/website_preview.js b/addons/website/static/src/client_actions/website_preview/website_preview.js index aae14db8e00..85329f8d61c 100644 --- a/addons/website/static/src/client_actions/website_preview/website_preview.js +++ b/addons/website/static/src/client_actions/website_preview/website_preview.js @@ -10,6 +10,7 @@ import { unslugHtmlDataObject } from '../../services/website_service'; import {OptimizeSEODialog} from '@website/components/dialog/seo'; import { routeToUrl } from "@web/core/browser/router_service"; import { getActiveHotkey } from "@web/core/hotkeys/hotkey_service"; +import wUtils from 'website.utils'; const { Component, onWillStart, onMounted, onWillUnmount, useRef, useEffect, useState } = owl; @@ -53,7 +54,16 @@ export class WebsitePreview extends Component { this.backendWebsiteId = unslugHtmlDataObject(backendWebsiteRepr).id; const encodedPath = encodeURIComponent(this.path); - if (this.websiteDomain && this.websiteDomain !== window.location.origin) { + if (this.websiteDomain && !wUtils.isHTTPSorNakedDomainRedirection(this.websiteDomain, window.location.origin)) { + // The website domain might be the naked one while the naked one + // is actually redirecting to `www` (or the other way around). + // In such a case, we need to consider those 2 from the same + // domain and let the iframe load that "different" domain. The + // iframe will actually redirect to the correct one (naked/www), + // which will ends up with the same domain as the parent window + // URL (event if it wasn't, it wouldn't be an issue as those are + // really considered as the same domain, the user will share the + // same session and CORS errors won't be a thing in such a case) window.location.href = `${this.websiteDomain}/web#action=website.website_preview&path=${encodedPath}&website_id=${this.websiteId}`; } else { this.initialUrl = `/website/force/${this.websiteId}?path=${encodedPath}`; diff --git a/addons/website/static/src/js/utils.js b/addons/website/static/src/js/utils.js index 75cef2c55c2..294c57dacd7 100644 --- a/addons/website/static/src/js/utils.js +++ b/addons/website/static/src/js/utils.js @@ -239,6 +239,28 @@ function websiteDomain(self) { return ['|', ['website_id', '=', false], ['website_id', '=', websiteID]]; } +/** + * Checks if the 2 given URLs are the same, to prevent redirecting uselessly + * from one to another. + * It will consider naked URL and `www` URL as the same URL. + * It will consider `https` URL `http` URL as the same URL. + * + * @param {string} url1 + * @param {string} url2 + * @returns {Boolean} + */ +function isHTTPSorNakedDomainRedirection(url1, url2) { + try { + url1 = new URL(url1).host; + url2 = new URL(url2).host; + } catch { + // Incorrect URL, `false` URL.. + return false; + } + return url1 === url2 || + url1.replace(/^www\./, '') === url2.replace(/^www\./, ''); +} + function sendRequest(route, params) { function _addInput(form, name, value) { let param = document.createElement('input'); @@ -389,6 +411,7 @@ return { prompt: prompt, sendRequest: sendRequest, websiteDomain: websiteDomain, + isHTTPSorNakedDomainRedirection: isHTTPSorNakedDomainRedirection, svgToPNG: svgToPNG, generateGMapIframe: generateGMapIframe, generateGMapLink: generateGMapLink, diff --git a/addons/website/static/src/systray_items/website_switcher.js b/addons/website/static/src/systray_items/website_switcher.js index 4da8f3f7493..3283c26f263 100644 --- a/addons/website/static/src/systray_items/website_switcher.js +++ b/addons/website/static/src/systray_items/website_switcher.js @@ -4,6 +4,7 @@ import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { Dropdown } from "@web/core/dropdown/dropdown"; import { DropdownItem } from "@web/core/dropdown/dropdown_item"; +import wUtils from 'website.utils'; const { Component } = owl; @@ -17,7 +18,7 @@ export class WebsiteSwitcherSystray extends Component { name: website.name, id: website.id, callback: () => { - if (website.domain && website.domain !== window.location.origin) { + if (website.domain && !wUtils.isHTTPSorNakedDomainRedirection(website.domain, window.location.origin)) { const { location: { pathname, search, hash } } = this.websiteService.contentWindow; const path = pathname + search + hash; window.location.href = `${website.domain}/web#action=website.website_preview&path=${encodeURI(path)}&website_id=${website.id}`;