Introdução
Instalação
Guias
- Engine
- Profile
- Browser
- BrowserView
- Navegação
- Conteúdo
- DOM
- JavaScript
- Pop-ups
- Diálogos
- Downloads
- Rede
- Cache
- Cookies
- Proxy
- Autenticação
- Plugins
- Impressão
- Senhas
- Perfis de dados do Usuário
- Cartões de Crédito
- Mídia
- Área de transferência
- Zoom
- Corretor Ortográfico
- Implantação
- Chromium
Resolução de Problemas
Navegação
Este guia descreve os eventos de navegação e mostra como carregar URLs e arquivos, filtrar requests de navegação, trabalhar com o histórico de navegação, etc.
Carregando URL
Para navegar para um recurso identificado por um URL, você pode utilizar um dos seguintes métodos:
Navigation.loadUrl(String url)
Navigation.loadUrl(LoadUrlParams params)
O exemplo a seguir mostra como navegar para https://www.google.com
utilizando o método Navigation.loadUrl(String)
:
Navigation navigation = browser.navigation();
navigation.loadUrl("https://www.google.com");
val navigation = browser.navigation()
navigation.loadUrl("https://www.google.com")
O código acima solicita a navegação para o recurso fornecido e sai imediatamente. Ele não espera até que o recurso seja completamente carregado.
Se for necessário bloquear a execução do thread atual até que o recurso seja carregado completamente, utilize o método Navigation.loadUrlAndWait(String url, Duration timeout)
:
navigation.loadUrlAndWait("https://www.google.com", Duration.ofSeconds(45));
navigation.loadUrlAndWait("https://www.google.com", Duration.ofSeconds(45))
Este método bloqueia a execução do segmento atual até que o frame principal do recurso seja completamente carregado ou até que o tempo limite de 45 segundos seja atingido.
Se a navegação falhar, será lançada a exceção NavigationException
.
Se o recurso não tiver sido carregado dentro de um período de tempo limite, será lançada a exceção TimeoutException
.
Carregando URL com POST
Para carregar uma página da Web e enviar dados POST, use o método Navigation.loadUrl(LoadUrlParams)
. O seguinte código
demonstra como formar os dados POST e enviá-los para o URL.
TextData data = TextData.of("post data");
LoadUrlParams params = LoadUrlParams.newBuilder(url)
.uploadData(data)
.addExtraHeader(HttpHeader.of("Content-Type", "text/plain"))
.build();
navigation.loadUrl(params);
val data = TextData.of("post data")
val params = LoadUrlParams.newBuilder(url)
.uploadData(data)
.addExtraHeader(HttpHeader.of("Content-Type", "text/plain"))
.build()
navigation.loadUrl(params)
Outros tipos de dados POST também estão disponíveis:
MultipartFormData
,
FormData
,
ByteData
.
Carregando Arquivo
Você pode utilizar os mesmos métodos para carregar arquivos HTML a partir do sistema de arquivos local. Você só precisa fornecer um caminho absoluto para o arquivo HTML em vez de um URL.
Por exemplo:
navigation.loadUrl(new File("index.html").getAbsolutePath());
navigation.loadUrl(File("index.html").absolutePath)
Carregando HTML
Esta seção descreve como carregar HTML num Frame
.
Existem duas abordagens possíveis para fazê-lo:
- Gerando e carregando URL de Dados.
- Registrando um Esquema Personalizado e interceptando requests de URL específicos.
Estas abordagens apresentam as seguintes diferenças:
Funcionalidade | URL de Dados | Esquema Personalizado |
---|---|---|
Suporte da ponte JavaScript-Java | sim | sim |
Suporte de InjectJsCallback | sim | sim |
Suporte de InjectCssCallback | sim | sim |
Carregando <iframe> do HTTP | sim | sim |
Carregando <iframe> do sistema de arquivos | não | não |
Carregamento de imagens a partir de HTTP | sim | sim |
Carregar imagens do sistema de arquivos | não | não |
Produção de eventos em rede | não | sim |
Produção de eventos de navegação | sim | sim |
Mostrar PDF e pré-visualização de impressão | sim | sim |
Mostrar PDF e pré-visualização de impressão em <iframe> | sim | sim |
URL de Dados
A ideia desta abordagem é converter o HTML necessário numa string base64
, gerar o URI de Dados com a string convertida e carregar este URL como mostrado abaixo:
String html = "<html><body>Hello</body></html>";
String base64Html = Base64.getEncoder().encodeToString(html.getBytes(UTF_8));
String dataUrl = "data:text/html;charset=utf-8;base64," + base64Html;
browser.navigation().loadUrl(dataUrl);
val html = "<html><body>Hello</body></html>"
val base64Html = Base64.getEncoder().encodeToString(html.toByteArray(UTF_8))
val dataUrl = "data:text/html;charset=utf-8;base64,$base64Html"
browser.navigation().loadUrl(dataUrl)
Também é possível utilizar o método Frame.loadHtml(String html)
, que gera automaticamente o URI de Dados a partir do HTML fornecido:
String html = "<html><body>Hello</body></html>";
browser.mainFrame().ifPresent(frame -> frame.loadHtml(html));
val html = "<html><body>Hello</body></html>"
browser.mainFrame().ifPresent { frame -> frame.loadHtml(html) }
A string URL não deve exceder o comprimento de 2MB devido ao limite do Chromium. Uma tentativa de carregar uma string URL que exceda este limite será ignorada pelo Chromium.
Esquema Personalizado
Outra abordagem para carregar HTML a partir de uma string é baseada em InterceptUrlRequestCallback
. A ideia é
registrar a chamada de retorno e interceptar um request de URL específico para devolver o HTML necessário como uma resposta HTTP. Por exemplo:
InterceptUrlRequestCallback interceptCallback = params -> {
if (params.urlRequest().url().endsWith("?hello")) {
byte[] bytes = "<html><body>Hello</body></html>".getBytes();
UrlRequestJob job = params.newUrlRequestJob(
UrlRequestJob.Options
.newBuilder(HttpStatus.OK)
.addHttpHeader(HttpHeader.of("Content-Type", "text/html"))
.build());
job.write(bytes);
job.complete();
return Response.intercept(job);
}
return Response.proceed();
};
EngineOptions options = EngineOptions.newBuilder(renderingMode)
.addScheme(HTTP, interceptCallback)
.build();
Engine engine = Engine.newInstance(options);
Browser browser = engine.newBrowser();
browser.navigation().loadUrl("http://load.html/?hello");
val interceptCallback = InterceptUrlRequestCallback { params ->
if (params.urlRequest().url().endsWith("?hello")) {
val bytes = "<html><body>Hello</body></html>".toByteArray()
val job = params.newUrlRequestJob(
UrlRequestJob.Options
.newBuilder(HttpStatus.OK)
.addHttpHeader(HttpHeader.of("Content-Type", "text/html"))
.build()
)
job.write(bytes)
job.complete()
Response.intercept(job)
} else {
Response.proceed()
}
}
val options = EngineOptions.newBuilder(renderingMode)
.addScheme(HTTP, interceptCallback)
.build()
val engine = Engine.newInstance(options)
val browser = engine.newBrowser()
browser.navigation().loadUrl("http://load.html/?hello")
O pedido de URL que termina com ?hello
será interceptado e o HTML <html><body>Hello</body></html>
será carregado no navegador.
Recarregando
Existem várias opções para recarregar a página Web atualmente carregada:
Recarregar utilizando a cache HTTP:
navigation.reload();
navigation.reload()
Recarregar ignorando a cache HTTP:
navigation.reloadIgnoringCache();
navigation.reloadIgnoringCache()
Recarregar utilizando a cache HTTP e verificar se há repostagem:
navigation.reloadAndCheckForRepost();
navigation.reloadAndCheckForRepost()
Recarregar ignorando a cache HTTP e verificar se há repostagem:
navigation.reloadIgnoringCacheAndCheckForRepost();
navigation.reloadIgnoringCacheAndCheckForRepost()
Parando
Utilize o método Navigation.stop()
para cancelar qualquer operação de navegação ou download pendente e parar qualquer elemento dinâmico da página, como sons de fundo e animações. Por exemplo:
navigation.stop();
navigation.stop()
Voltar & Avançar
O JxBrowser permite trabalhar com a lista do histórico de navegação voltar e avançar.
Quando você cria uma instância Browser
ele navega para a página web about:blank
por padrão, então há sempre uma entrada na lista de navegação voltar e avançar.
Para carregar a localização anterior na lista de voltar e avançar, utilize a seguinte abordagem:
if (navigation.canGoBack()) {
navigation.goBack();
}
if (navigation.canGoBack()) {
navigation.goBack()
}
Para carregar a localização seguinte na lista voltar e avançar, utilize:
if (navigation.canGoForward()) {
navigation.goForward();
}
if (navigation.canGoForward()) {
navigation.goForward()
}
Para navegar para a entrada num índice específico na lista voltar e avançar, utilize:
if (index >= 0 && index < navigation.entryCount()) {
navigation.goToIndex(index);
}
if (index >= 0 && index < navigation.entryCount()) {
navigation.goToIndex(index)
}
Você pode percorrer a lista voltar e avançar e obter detalhes sobre cada entrada de navegação:
for (int index = 0; index < navigation.entryCount(); index++) {
NavigationEntry navigationEntry = navigation.entryAtIndex(index);
System.out.println("URL: " + navigationEntry.url());
System.out.println("Title: " + navigationEntry.title());
}
for (index in 0 until navigation.entryCount()) {
val navigationEntry = navigation.entryAtIndex(index)
println("URL: ${navigationEntry.url()}")
println("Title: ${navigationEntry.title()}")
}
Você pode modificar a lista voltar e avançar removendo as entradas:
// Devolve o número de entradas na lista de voltar/avançar.
int entryCount = navigation.entryCount();
// Remover entradas de navegação no índice.
for (int i = entryCount - 2; i >= 0; i--) {
boolean success = navigation.removeEntryAtIndex(i);
System.out.println("Was the navigation entry at the index " + i +
" successfully removed? " + success);
}
// Retorna o número de entradas na lista de retrocesso/avanço.
val entryCount = navigation.entryCount()
// Remover entradas de navegação no índice.
for (i in entryCount - 2 downTo 0) {
val success = navigation.removeEntryAtIndex(i)
println("A entrada de navegação no índice $i foi removida com êxito? $success")
}
Filtragem de URLs
Você pode decidir se o request de navegação para um URL específico deve ser ignorado ou não.
O código seguinte demonstra como ignorar os requests de navegação para todos os URLs que começam por https://www.google
:
navigation.set(StartNavigationCallback.class, params -> {
// Ignore navigation requests to the URLs that start
// with "https://www.google"
if (params.url().startsWith("https://www.google")) {
return Response.ignore();
}
return Response.start();
});
navigation.set(StartNavigationCallback::class.java, StartNavigationCallback { params ->
// Ignore navigation requests to the URLs that start
// with "https://www.google"
if (params.url().startsWith("https://www.google")) {
Response.ignore()
} else {
Response.start()
}
})
Filtragem de Recursos
Utilizando a chamada de retorno BeforeUrlRequestCallback
você pode determinar se os recursos como HTML, imagem, arquivo JavaScript ou CSS, favicon, etc. devem ser carregados. Por padrão, todos os recursos são carregados. Para modificar o comportamento padrão, registre a sua própria implementação de retorno de chamada onde você decide quais recursos devem ser cancelados ou carregados.
O exemplo seguinte demonstra como suprimir todas as imagens:
Network network = engine.network();
network.set(BeforeUrlRequestCallback.class, params -> {
if (params.urlRequest().resourceType() == IMAGE) {
return BeforeUrlRequestCallback.Response.cancel();
}
return BeforeUrlRequestCallback.Response.proceed();
});
val network = engine.network()
network.set(BeforeUrlRequestCallback::class.java, BeforeUrlRequestCallback { params ->
if (params.urlRequest().resourceType() === IMAGE) {
BeforeUrlRequestCallback.Response.cancel()
} else {
BeforeUrlRequestCallback.Response.proceed()
}
})
Eventos de Navegação
O carregamento de uma página Web é um processo complexo durante o qual são acionados diferentes eventos de navegação. O diagrama seguinte mostra a ordem pela qual os eventos de navegação podem ser acionados durante o carregamento de uma página Web:
Carregamento Iniciado
Para receber notificações quando o carregamento do conteúdo tiver começado, utilize o evento LoadStarted
. Por exemplo:
navigation.on(LoadStarted.class, event -> {});
navigation.on(LoadStarted::class.java) { event -> }
Este evento corresponde ao momento em que o spinner da aba começa a rodar.
Carregamento Concluído
Para receber notificações quando o carregamento do conteúdo tiver terminado, utilize o evento LoadFinished
. Por exemplo:
navigation.on(LoadFinished.class, event -> {});
navigation.on(LoadFinished::class.java) { event -> }
Este evento corresponde ao momento em que o spinner do separador para de rodar.
Navegação Iniciada
Para receber notificações sobre o início da navegação, utilize o evento NavigationStarted
. Por exemplo:
navigation.on(NavigationStarted.class, event -> {
String url = event.url();
// Indica se a navegação será realizada
// no escopo do mesmo documento.
boolean isSameDocument = event.isSameDocument();
});
navigation.on(NavigationStarted::class.java) { event ->
val url = event.url()
// Indica se a navegação será realizada
// no escopo do mesmo documento.
val isSameDocument = event.isSameDocument()
}
Navegação Interrompida
Para receber notificações quando a navegação for interrompida, utilize o evento NavigationStopped
. Por exemplo:
navigation.on(NavigationStopped.class, event -> {});
navigation.on(NavigationStopped::class.java) { event -> }
Este evento é disparado quando a navegação é interrompida através do método Navigation.stop()
.
Navegação Redirecionada
Para receber notificações quando a navegação tiver sido redirecionada para um novo URL, utilize o evento NavigationRedirected
. Por exemplo:
navigation.on(NavigationRedirected.class, event -> {
// O URL de redirecionamento da navegação.
String url = event.destinationUrl();
});
navigation.on(NavigationRedirected::class.java) { event ->
// O URL de redirecionamento da navegação.
val url = event.destinationUrl()
}
Navegação Concluída
Para receber notificações quando a navegação tiver terminado, utilize o evento NavigationFinished
. Por exemplo:
navigation.on(NavigationFinished.class, event -> {
String url = event.url();
Frame frame = event.frame();
boolean hasCommitted = event.hasCommitted();
boolean isSameDocument = event.isSameDocument();
boolean isErrorPage = event.isErrorPage();
if (isErrorPage) {
NetError error = event.error();
}
});
navigation.on(NavigationFinished::class.java) { event ->
val url = event.url()
val frame = event.frame()
val hasCommitted = event.hasCommitted()
val isSameDocument = event.isSameDocument()
val isErrorPage = event.isErrorPage()
if (isErrorPage) {
val error = event.error()
}
}
Este evento é ativado quando a navegação é confirmada, abortada ou substituída por uma nova. Para saber se a navegação foi confirmada, utilize NavigationFinished.hasCommitted()
; utilize NavigationFinished.isErrorPage()
para saber se a navegação resultou em uma página de erro.
Se o evento for chamado porque a navegação foi comprometida, o carregamento do documento ainda estará em curso.
O evento é disparado por navegações do tipo mesmo documento (no escopo do mesmo documento), como navegações de fragmentos ou window.history.pushState()
/window.history.replaceState()
, que não resultarão em uma mudança de documento. Utilize NavigationFinished.isSameDocument()
para verificar se a navegação é do mesmo documento.
Carregamento do Frame Concluído
Para receber notificações quando o conteúdo carregado no Frame
tiver terminado, por favor use o evento FrameLoadFinished
. Por exemplo:
navigation.on(FrameLoadFinished.class, event -> {
String url = event.url();
Frame frame = event.frame();
});
navigation.on(FrameLoadFinished::class.java) { event ->
val url = event.url()
val frame = event.frame()
}
Este evento corresponde ao momento em que o conteúdo do Frame
foi completamente carregado.
Falha no Carregamento do Frame
Para receber notificações quando o conteúdo carregado no Frame
falhou por algum motivo, use o evento FrameLoadFailed
. Por exemplo:
navigation.on(FrameLoadFailed.class, event -> {
String url = event.url();
NetError error = event.error();
});
navigation.on(FrameLoadFailed::class.java) { event ->
val url = event.url()
val error = event.error()
}
Carregamento do Documento Frame Concluído
Para receber notificações quando o carregamento do documento Frame
tiver terminado, por favor use o evento FrameDocumentLoadFinished
. Por exemplo:
navigation.on(FrameDocumentLoadFinished.class, event -> {
Frame frame = event.frame();
});
navigation.on(FrameDocumentLoadFinished::class.java) { event ->
val frame = event.frame()
}
Nesta altura, os scripts diferidos foram executados e os scripts de conteúdo marcados com “document_end” são injetados no frames.