Search code examples
javachromiumkotlinjxbrowser

JxBrowser strategy for efficiently retrieving favicon


As far as I can tell there is no infrastructure for favicons in JxBrowser. Shouldn't the favicon be a part of the title event ? I'm thinking my best bet is to just go for http://<domain>/favicon.ico but this is going to be so much redundant work (http client and caching mechanism).

Is there any way I can use the JxBrowser to take care of this elegantly?

I've tried two strategies for trying to reliably get a hold of the resources, it's not reliable enough though:

Event based url acquisition (ResourceType.FAVICON is never seen):

browser.context.networkService.resourceHandler = object : ResourceHandler {
    override fun canLoadResource(p0: ResourceParams?): Boolean {
        if (p0!!.resourceType == ResourceType.FAVICON) println(p0!!.url)
        if (p0!!.resourceType == ResourceType.IMAGE && p0.url.contains("favicon")) println("found favicon url: ${p0.url}")
        return true
    }
}

// xpath based approach

browser.addLoadListener(object : LoadListener {
    override fun onDocumentLoadedInMainFrame(p0: LoadEvent) {
        p0.inSwingThread {
            val res = it.browser.document.findElements(By.xpath("//link[@rel=\"icon\" or @rel=\"shortcut icon\"]"))
            res.forEach {
                println("----------")
                it.attributes.forEach { println(it.key + " " + it.value) }
            }
        }
    }
    // ...
}

Solution

  • Right now JxBrowser API doesn't provide functionality that allows downloading the favicon.ico file. I recommend that you use standard Java API and the approach with http://<domain>/favicon.ico. For example:

    URL url = new URL("http://stackoverflow.com/favicon.ico");
    InputStream in = new BufferedInputStream(url.openStream());
    OutputStream out = new BufferedOutputStream(new FileOutputStream("D:/favicon.ico"));
    for ( int i; (i = in.read()) != -1; ) {
        out.write(i);
    }
    in.close();
    out.close();