Ошибка навигации в Chrome 61+ на Android

Я создаю страницу входа, которая после отправки и проверки учетных данных пользователя открывает собственное мобильное приложение. До прошлой недели у меня была эта рабочая кросс-мобильная ОС с использованием пользовательского URI-схемы, например:

function onLoginCallback() {
    const redirectUri = 'customscheme:/action?param1=val1&param2=val2';
    window.location.replace(redirectUri);
}

Страница входа отображается в IABT, сокращенно от вкладки "В браузере приложений".

Однако с момента выхода версии 61 Chrome этот подход не работает на Android. Chrome блокирует перенаправление, потому что нет никаких видимых действий пользователя, связанных с перенаправлением (см. здесь для получения дополнительной информации по этому вопросу).

Как следствие, при выполнении приведенного выше кода я получу предупреждение в консоли:

Navigation is blocked: customscheme: /action?param1=val1¶m2=val2

Я также попытался обновить URL-адрес пользовательской схемы до целевого URL, но безрезультатно. Поиск в Google по этому вопросу не может дать четкого решения, поэтому я надеюсь, что кто-нибудь может мне помочь.


Изменить: Попытка воспроизвести проблему по следующему сценарию (как можно ближе к реальному сценарию):

  • IABT отображает страницу одной кнопкой
  • Нажатие на кнопку запускает вызов jsonp в фиктивную конечную точку
  • Обратный вызов JSONP выполняется и запускает пользовательское событие
  • Обработчик события для пользовательского события запускается и перенаправляет браузер на другую фиктивную конечную точку
  • Эта фиктивная конечная точка отвечает 302 на пользовательскую схему Deeplink.

Увы, похоже, это работает. Я ожидал, что включение вызова jsonp заставит Chrome заблокировать окончательное перенаправление, поскольку он не сможет идентифицировать его как действие, инициированное пользователем.


Редактировать 2: удалось получить воспроизводимый сценарий. Мы создали фиктивную конечную точку, которая по запросу просто возвращает 302 с пользовательской схемой в заголовке Location. Это блокируется на все попытки, кроме первой. Этот факт все еще поражает разум. Мы используем приложение AppAuth для Android для проверки настроек.

Я открываю пользовательскую вкладку для конечной точки, как показано ниже. Код взят из этого ответа.

void launchTab(Context context, Uri uri){
    final CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
        @Override
        public void onCustomTabsServiceConnected(ComponentName componentName, CustomTabsClient client) {
            final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
            final CustomTabsIntent intent = builder.build();
            client.warmup(0L); // This prevents backgrounding after redirection
            intent.launchUrl(context, uri);
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    CustomTabsClient.bindCustomTabsService(context, "com.android.chrome", connection);
}

Ответ 1

В итоге мы внедрили наши формы для входа и регистрации с помощью классического шаблона post-redirect-get.

Сервер отвечает 302 на пользовательскую схему URI. Поскольку в этой настройке нет асинхронного выполнения между пользователем, отправляющим форму, и браузером, получающим перенаправление, Chrome правильно определяет цепочку действий как доверенную и, таким образом, не блокирует навигацию.

Я понимаю, что это не может быть предпочтительным решением для всех. Возможной альтернативой для поддержки асинхронных потоков выполнения является использование универсальных ссылок, поскольку в них используются обычные схемы http (s), к которым перенаправления (на момент публикации моего вопроса) не считались вредными для Chrome.