From 67b2545e49f0ae4ef6aaba20726fa8ea8f2e9242 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20E=C3=9Fl?= <indy.essl@gmail.com>
Date: Wed, 12 Apr 2023 08:05:51 +0200
Subject: [PATCH] [BUGFIX] Fix page reloading on click on preview button
 (again)

The changes introduced in #93706 broke the preview button functionality
in multidomain setups. When first previewing the page in one page tree
and then clicking the preview link in the page tree of a different
domain, a DOMException due to a cross origin error would be triggered
in JavaScript, because it is not allowed to access the constructor of
a window object from a different context.

The thrown DOMException is now properly caught.

Resolves: #99286
Related: #93706
Releases: main, 11.5
Change-Id: I709f06ef89e248d7b88d500281e708f56557a176
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/78571
Tested-by: core-ci <typo3@b13.com>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
---
 .../Resources/Public/TypeScript/WindowManager.ts    | 13 ++++++++++---
 .../Resources/Public/JavaScript/WindowManager.js    |  2 +-
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/WindowManager.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/WindowManager.ts
index bf437deafcd8..bbba5b524dc6 100644
--- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/WindowManager.ts
+++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/WindowManager.ts
@@ -37,9 +37,16 @@ class WindowManager {
       switchFocus = true;
     }
     const existingWindow = this.windows[windowName] ?? window.open('', windowName, windowFeatures);
-    // Note: `existingWindow instanceof Window` wouldn't work here as `existingWindow` is from a another browser context/window.
-    // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_contexts_e.g._frames_or_windows
-    const isInstanceOfWindow = existingWindow.constructor.name === 'Window';
+    let isInstanceOfWindow = false;
+    try {
+      // Note: `existingWindow instanceof Window` wouldn't work here as `existingWindow` is from another browser context/window.
+      // Note: this will still fail if `existingWindow` points to a cross-origin frame
+      // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms
+      isInstanceOfWindow = existingWindow.constructor.name === 'Window';
+    } catch (DOMException) {
+      // Intended fall-thru
+      // DOMException is thrown if existingWindow points to a cross-origin frame which we're not allowed to access
+    }
     const existingUri = isInstanceOfWindow && !existingWindow.closed ? existingWindow.location.href : null;
 
     if (Utility.urlsPointToSameServerSideResource(uri, existingUri)) {
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/WindowManager.js b/typo3/sysext/backend/Resources/Public/JavaScript/WindowManager.js
index 89db29243eed..8395f1b7e3f1 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/WindowManager.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/WindowManager.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-var __importDefault=this&&this.__importDefault||function(n){return n&&n.__esModule?n:{default:n}};define(["require","exports","TYPO3/CMS/Backend/Utility"],(function(n,o,e){"use strict";e=__importDefault(e);class t{constructor(){this.windows={},this.open=(...n)=>this._localOpen.apply(this,n),this.globalOpen=(...n)=>this._localOpen.apply(this,n),this.localOpen=(n,o,e="newTYPO3frontendWindow",t="")=>this._localOpen(n,o,e,t)}_localOpen(n,o,t="newTYPO3frontendWindow",i=""){var l;if(!n)return null;null===o?o=!window.opener:void 0===o&&(o=!0);const r=null!==(l=this.windows[t])&&void 0!==l?l:window.open("",t,i),s="Window"===r.constructor.name&&!r.closed?r.location.href:null;if(e.default.urlsPointToSameServerSideResource(n,s))return r.location.replace(n),r.location.reload(),r;const a=window.open(n,t,i);return this.windows[t]=a,o&&a.focus(),a}}const i=new t;return top.TYPO3.WindowManager||(top.document===window.document?top.TYPO3.WindowManager=i:top.TYPO3.WindowManager=new t),i}));
\ No newline at end of file
+var __importDefault=this&&this.__importDefault||function(n){return n&&n.__esModule?n:{default:n}};define(["require","exports","TYPO3/CMS/Backend/Utility"],(function(n,o,t){"use strict";t=__importDefault(t);class e{constructor(){this.windows={},this.open=(...n)=>this._localOpen.apply(this,n),this.globalOpen=(...n)=>this._localOpen.apply(this,n),this.localOpen=(n,o,t="newTYPO3frontendWindow",e="")=>this._localOpen(n,o,t,e)}_localOpen(n,o,e="newTYPO3frontendWindow",i=""){var l;if(!n)return null;null===o?o=!window.opener:void 0===o&&(o=!0);const r=null!==(l=this.windows[e])&&void 0!==l?l:window.open("",e,i);let s=!1;try{s="Window"===r.constructor.name}catch(n){}const a=s&&!r.closed?r.location.href:null;if(t.default.urlsPointToSameServerSideResource(n,a))return r.location.replace(n),r.location.reload(),r;const c=window.open(n,e,i);return this.windows[e]=c,o&&c.focus(),c}}const i=new e;return top.TYPO3.WindowManager||(top.document===window.document?top.TYPO3.WindowManager=i:top.TYPO3.WindowManager=new e),i}));
\ No newline at end of file
-- 
GitLab