Um link ou window.open dentro de um WebView não abre uma nova aba — não faz nada, em silêncio. No Android o padrão é setSupportMultipleWindows(false), que ignora todo pedido de abrir nova janela; para funcionar a app precisa ativar múltiplas janelas e implementar onCreateWindow e onCloseWindow, e a maioria nunca faz. No iOS, o delegado createWebViewWithConfiguration do WKWebView retorna nil por padrão, então target=_blank é descartado em silêncio a menos que a app implemente WKUIDelegate — e quando fazem, costumam criar um segundo WKWebView cujo histórico de voltar e avançar está desconectado do primeiro. Um runtime próprio do host traz um único gerenciador de janelas que mapeia popups para abas no app ou para um encaminhamento externo coerente, mantém o histórico intacto e nunca deixa um link morrer em silêncio.
Android: novas janelas ignoradas por padrão
A documentação do Android é direta: por padrão o sistema ignora pedidos de abrir novas janelas, seja via JavaScript ou via atributo target. Para respeitar target=_blank a app deve chamar setSupportMultipleWindows(true) e sobrescrever onCreateWindow (e onCloseWindow para limpar). Falta a flag e onCreateWindow nunca é chamado — o toque não gera navegação, nem erro, nada. O resultado prático no ecossistema é uma longa cauda de links mortos de "abrir em nova aba" que funcionam num navegador real e somem no WebView.
iOS: o delegado que retorna nil
O WKWebView não tem um modelo de abas ou janelas embutido; quando a página pede um novo contexto de navegação, ele pergunta à app via WKUIDelegate.createWebViewWithConfiguration. A implementação padrão retorna nil, o que significa que target=_blank e window.open são descartados em silêncio. Os desenvolvedores precisam definir o uiDelegate e implementar o método; a solução comum recarrega o pedido na mesma view (perdendo a semântica de nova aba) ou cria um WKWebView totalmente novo — cujo histórico de voltar e avançar é independente do original, então o usuário fica preso sem volta.
O que se perde sem um gerenciador de janelas
- Links mortos sem feedback. Toques target=_blank não fazem nada, então o usuário acha que a página quebrou.
- Histórico quebrado. Um segundo WebView tem seu próprio histórico de voltar/avançar, desconectando o usuário de onde veio.
- Sem política coerente de links externos. Alguns links deveriam ficar no app, outros ir para o navegador do sistema; um WebView de fábrica não tem regra.
- Contexto de sessão perdido. Um popup que deveria herdar login ou carrinho inicia frio num contexto à parte.
- Divergência silenciosa. O mesmo HTML abre uma aba real no Safari e não faz nada na view embutida.
A solução do runtime
Um runtime próprio do host traz um único gerenciador de janelas abaixo da página. Mapeia cada pedido de nova janela para um resultado previsível — uma aba no app que compartilha o histórico e a sessão, ou um encaminhamento externo claramente rotulado para o navegador do sistema — e nunca engole um link em silêncio. O autor da página escreve um target=_blank padrão, e o runtime decide, de forma coerente e por política, o que acontece a seguir, em ambas as plataformas.
| Dimensão | WebView | Runtime próprio do host |
|---|---|---|
| Nova janela por padrão | Ignorada (Android) / delegado nil (iOS) | Mapeada para aba ou encaminhamento |
| Flag Android | setSupportMultipleWindows + onCreateWindow | Gerenciado pelo runtime |
| Caminho iOS | WKUIDelegate.createWebViewWithConfiguration | Gerenciado pelo runtime |
| Histórico de navegação | Quebrado numa segunda view | Compartilhado, intacto |
| Política de links externos | Nenhuma, adivinhação por app | Coerente, configurável |
| Links mortos em silêncio | Comuns | Nunca |
Um navegador trata target=_blank como uma promessa: um contexto novo e alcançável. Um WebView de fábrica o trata como um pedido que é livre para ignorar. Um runtime restaura a promessa — um gerenciador de janelas, histórico intacto e um link que sempre vai a um lugar que o usuário consegue ver.
Fontes
- Android Developers — WebView 'Managing windows': pedidos de nova janela ignorados por padrão; exige setSupportMultipleWindows + onCreateWindow — o padrão que descarta popups.
- Stack Overflow — onCreateWindow não é chamado a menos que setSupportMultipleWindows(true) — a flag faltante que mata o link.
- Apple Developer — WKUIDelegate createWebViewWithConfiguration: nil por padrão descarta target=_blank — o caminho silencioso no iOS.
- Filip Němeček — Como abrir links target=_blank no WKWebView no iOS — por que os links não fazem nada e o conserto do delegado.
- MDN — Referência do atributo target=_blank — o padrão web que o WebView viola em silêncio.