Возврат на opener вкладку браузера после закрытия дочерней (открытой по window.open)

Открываем вкладку 1, открываем вкладку 4 с посторонним сайтом. Возвращаемся на вкладку 1. Из вкладки 1 открываем новую вкладку 2 через window.open. Из вкладки 2 открываем новую вкладку 3 через window.open.

Пользователь закрывает вкладку 3 через window.close, становится активной вкладка 2. Вкладку 2 закрывает через window.close. Становится активной вкладка 4 с посторонним сайтом. Почему не выполняется возврат на вкладку 1?

Логика выглядит так: браузер запоминает последний opener, при этом если перед закрытием была открыта другая вкладка - возврат будет на следующую после закрытой. Как будто opener запоминается до следующего перехода на другую вкладку.

Вкладки 1, 2, 3 принадлежат одному домену. Вкладка 4 может быть открыта в любое время.

Пробовал так же прокидывать событие и на родительской и делать window.focus(); Код отрабатывает, но действие не происходит.

Не нашел нигде точного объяснения такому поведению, везде +- "особенности политик безопасности браузера". Chrome (135, 105), Mozilla работают одинаково. Может быть, кто-то точно знает, почему такое поведение?

upd: не работает ни один из возможных вариантов, будь то window.focus(), обращение через opener, подмена window.location.href и т.п. Видимо, политики безопасности браузера не позволяют делать такое.

index.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Главная страница</title>
</head>
<body>
    <h1>Главная страница</h1>
    <p>Нажмите кнопку, чтобы открыть Страницу 1 в новой вкладке.</p>
    
    <button onclick="openPage1()">Открыть Страницу 1</button>

    <script>
        function openPage1() {
            window.open('page1.html', '_blank'); // Открываем page1.html в новой вкладке
        }
    </script>
</body>
</html>

page1.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Страница 1</title>
</head>
<body>
    <h1>Страница 1</h1>
    <p>Это Страница 1. Нажмите кнопку, чтобы открыть Страницу 2 в новой вкладке.</p>
    
    <button onclick="openPage2()">Открыть Страницу 2</button>
    <button onclick="window.close()">Закрыть это окно</button>

    <script>
        function openPage2() {
            window.open('page2.html', '_blank'); // Открываем page2.html в новой вкладке
        }
    </script>
</body>
</html>

page2.html

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Страница 2</title>
</head>
<body>
    <h1>Страница 2</h1>
    <button onclick="window.close()">Закрыть это окно</button>
</body>
</html>


Ответы (1 шт):

Автор решения: Виктор Карев

Как я понял, задача состоит в том, чтобы из вкладки 1 открыть вкладку 2, а при нажатии на какую-то кнопку на вкладке 2, вкладку 2 закрыть и вернуться на вкладку 1. Дело в том, что дочерняя вкладка не может командовать родительской, но родительская может командовать дочерней. Поэтому мы из дочерней вкладки посылаем сообщение в родительскую, а затем уже родительская принимает на себя фокус и закрывает дочернюю.

  1. При создании дочерней вкладки 2, запоминаем её и переключаемся на дочернюю:
function onCreateWindow2(){
    window.addEventListener('message', handleEvent, false); // слушатель сообщений
    var window2 = window.open(location, 'window2');
    window2.focus();
}
  1. Во вкладке 2 по нажатию на кнопку закрытия передаём сообщение вкладке 1:
function onClose(){
    if (!window.opener) { // родительская вкладка пропала...
        alert('???');
        return;
    }
    const d = {}; // какие-то данные, передаваемые вв вкладку 1
    window.opener.postMessage({d, action:'close'}, window.opener.location.href);
}
  1. Во вкладке 1 ловим сообщение и обрабатываем:
function handleEvent(event){
    if (event.origin !== window.origin) {
        return;
    }
    if (event.data.action == 'close') {
        window.focus();
        window2.close();
        window.removeEventListener('message', handleEvent, false); // слушатель больше не нужен
        ...
        дальше обрабатываем пришедшие данные
    }
}
→ Ссылка