class InterWindowMessaging { constructor(functionSet, targetWindow, targetOrigin) { // ... 既存のコード ... if (targetOrigin === "negotiation") { this.#targetOrigin = null; this.#isNegotiating = true; this.#negotiationKey = crypto.randomUUID(); // ネゴシエーション用の乱数を生成 } else { this.#targetOrigin = targetOrigin; this.#isNegotiating = false; } this.#setMessageListener(); this.#submitReady(); } // ... 既存のプライベートプロパティ ... #negotiationKey = null; #setMessageListener() { window.addEventListener("message", async (event) => { const origin = event.origin; // ... 既存のメッセージ解析ロジック ... // 親ウィンドウ(ネゴシエーションモードではない側)の処理 if (!this.#isNegotiating && msg.negotiationKey) { // 子から乱数を受け取ったら、そのまま返信 this.#postMessage({ ready: true, negotiationKey: msg.negotiationKey }); return; } // 子ウィンドウ(ネゴシエーションモード)の処理 if (this.#isNegotiating && !this.#targetOrigin) { if (msg.ready === true && msg.negotiationKey === this.#negotiationKey) { this.#targetOrigin = origin; this.#isNegotiating = false; this.#completeConnection(); return; } console.warn("Ignoring message during negotiation phase from:", origin); return; } // ... 既存のオリジンチェックとメッセージ処理 ... }); } #postMessage(messageObject, transferables = []) { // ... 既存のコード ... // ネゴシエーションモードで初期メッセージを送る場合のみ、ターゲットオリジンを`*`にする const postOrigin = this.#isNegotiating && !this.#targetOrigin ? "*" : this.#targetOrigin; if (transferables.length > 0) { targetWin.postMessage(messageObject, postOrigin, transferables); } else { targetWin.postMessage(JSON.stringify(messageObject), postOrigin); } } #submitReady() { let message; if (this.#isNegotiating) { // ネゴシエーション用の初期メッセージ message = { ready: true, negotiationKey: this.#negotiationKey }; } else { // 通常のreadyメッセージ message = { ready: true }; } this.#postMessage(message); } // ... その他のメソッド ... }