Bug 54024 - [Qt] QWebSettings::iconForURL() returns NULL at first call
Summary: [Qt] QWebSettings::iconForURL() returns NULL at first call
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Qt (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Nobody
URL:
Keywords: Qt, QtTriaged
Depends on:
Blocks:
 
Reported: 2011-02-08 11:23 PST by Stephen
Modified: 2014-02-03 03:17 PST (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stephen 2011-02-08 11:23:27 PST
I am running to an issue with QWebSettings::iconForURL. Let's assume an icon of a certain web page has been cached in the icon database in a previous session. In a fresh new session, the first call to QWebSettings::iconForURL will always return null. I have to wait for some time and then make a second call. The second call will return a valid icon. 

Here is the steps to produce the problem, 

1. Cache the icon by using QWebView to navigate to the target website first. Then close the application.

2. Restart the application, the first call to QWebSettings::iconForURL for the same URL will return null. 

3. Wait some time, make a second call to iconForURL, it will return a valid icon this time. 

4. If the two calls are made continuously without delay, both times will return null. 

So, to summarize, if an icon has been cached in a previous session, then the first call will return null. We have to wait some time and make a second call to get a valid icon. I believe a QWebView navigation also counts as a first time call. So, if you perform a navigation first and then make a call iconForURL in the same session, it will always succeed. 

The following code serves as a test case:

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWebSettings::setIconDatabasePath(".");

//run this for only once and then comment it out.
QWebView view;
view.load(QUrl("http://www.cnn.com/"));
view.show();
app.exec();

QIcon icon=QWebSettings::iconForUrl(QUrl("http://www.cnn.com/"));
QPushButton button;
button.setIcon(icon);
button.show();
app.exec();
icon=QWebSettings::iconForUrl(QUrl("http://www.cnn.com/"));
button.setIcon(icon);
button.show();
return app.exec();
}

Please cache the icon with QWebView when you run it for the first time. After that, comment out the code block related to QWebView. Then run it again. You will see that the first button has no icon while the second button has the cnn icon.
Comment 1 Benjamin Poulain 2011-02-09 04:30:30 PST
If I remember correctly, the WebKit code under QWebSettings::iconForURL() is asynchronous, and we present it as a synchronous API which fails when the data is not available.

I think the only way to get the icon systematically is to wait for the signal QWebFrame::iconChanged().

We should find a way to improve this or change the documentation. Devs are reporting problems regularily about QWebSettings::iconForUrl().
Comment 2 Stephen 2011-02-09 07:41:26 PST
I can understand it's asynchronous if it doesn't exist in the database and we need download it from the network. Why should it be asynchronous if it already exists in the database? Otherwise, that beats the purpose of having a local database. 

Developers like to use iconForURL to display icons for the bookmarks bar or bookmarks menu. We shouldn't rely on QWebFrame just to retrieve an icon from the database. 

Are you guys always checking for updates over network when iconForURL is called for the first time during a session? If that is the case, we'd hope there is an option to get it from cache only and return immediately. 

Thanks.
Comment 3 Antonio Gomes 2011-02-09 07:43:47 PST
is it a dup of bug 29440? (which was INVALID'ed)
Comment 4 Stephen 2011-02-09 08:07:33 PST
No. It isn't a dup of 29440. I did post my bug report in that thread sometime ago. But nobody responded since that thread is in "CLOSED" state. So I decided to initiate a new thread to get some fresh attention. I wouldn't mind if you guys close this one and reopen 29440 as long as the underlying issue gets fixed in the future.
Comment 5 Benjamin Poulain 2011-02-09 09:38:12 PST
(In reply to comment #2)
> I can understand it's asynchronous if it doesn't exist in the database and we need download it from the network. Why should it be asynchronous if it already exists in the database? Otherwise, that beats the purpose of having a local database.

Because the disk is slow as well, making asynchronous for I/O is often a good idea.

> Developers like to use iconForURL to display icons for the bookmarks bar or bookmarks menu. We shouldn't rely on QWebFrame just to retrieve an icon from the database. 

Rekonq devs gave up on ::iconForURL() because of this undefined behavior. I think it is worth investigation.
Comment 6 Stephen 2011-02-09 10:04:46 PST
I am not sure it's always asynchronous. The 2nd or 3rd calls always get a valid icon if it's in the database. Maybe, there is some internal icon cache in the memory. The first call only loads it from the disk into the memory while later calls directly retrieve the icon from the memory cache. 

A synchronous return option would be great in this case. Otherwise, we should provide some callback signal to let developers know when the icon is ready. And this signal shouldn't come from QWebFrame since there are cases we want to use the icon outside a webkit view. 

Just sharing some thoughts. Thanks.
Comment 7 Rafael Brandao 2011-11-28 13:55:09 PST
(In reply to comment #6)
> I am not sure it's always asynchronous. The 2nd or 3rd calls always get a valid icon if it's in the database. Maybe, there is some internal icon cache in the memory. The first call only loads it from the disk into the memory while later calls directly retrieve the icon from the memory cache. 
> 
> A synchronous return option would be great in this case. Otherwise, we should provide some callback signal to let developers know when the icon is ready. And this signal shouldn't come from QWebFrame since there are cases we want to use the icon outside a webkit view. 
> 
> Just sharing some thoughts. Thanks.

It happens because when you ask for the icon, it may not have finished to load the mapping between page urls and icon urls, or it has finished it but it didn't load the icon data yet. When you request the pixmap, then you'll be marked as interested in the data for that icon, and then when you get the signal iconChanged, it means it is ready... so you request it again and you'll get the QPixmap you were looking for.

You could ask for the pixmap in the call iconForURL with size (0,0) so it won't actually give you any data, but it will trigger the load for it. You should do this on startup.
Comment 8 Stephen 2011-11-28 15:16:05 PST
The point is that we need load the icon without creating any QWebView. For example, we would want to display the icon on a bookmark toolbar in a browser application. The iconChanged signal is part of QWebView class and we can't use that. We need some other way to determine when the icon is ready for use. 

(In reply to comment #7)
> 
> It happens because when you ask for the icon, it may not have finished to load the mapping between page urls and icon urls, or it has finished it but it didn't load the icon data yet. When you request the pixmap, then you'll be marked as interested in the data for that icon, and then when you get the signal iconChanged, it means it is ready... so you request it again and you'll get the QPixmap you were looking for.
> 
> You could ask for the pixmap in the call iconForURL with size (0,0) so it won't actually give you any data, but it will trigger the load for it. You should do this on startup.
Comment 9 Rafael Brandao 2011-11-28 15:52:04 PST
(In reply to comment #8)
> The point is that we need load the icon without creating any QWebView. For example, we would want to display the icon on a bookmark toolbar in a browser application. The iconChanged signal is part of QWebView class and we can't use that. We need some other way to determine when the icon is ready for use. 
> 
> (In reply to comment #7)
> > 
> > It happens because when you ask for the icon, it may not have finished to load the mapping between page urls and icon urls, or it has finished it but it didn't load the icon data yet. When you request the pixmap, then you'll be marked as interested in the data for that icon, and then when you get the signal iconChanged, it means it is ready... so you request it again and you'll get the QPixmap you were looking for.
> > 
> > You could ask for the pixmap in the call iconForURL with size (0,0) so it won't actually give you any data, but it will trigger the load for it. You should do this on startup.

Oh, I see... it seems that we need to expose the icon database itself. This way it would emit a signal like iconChangedForPageURL(url) and then the pages interested on the icon for that url would know that the pixmap is ready. As QWebSettings already has the function to request icons, maybe it's him the one that should also emit this kind of signal, but I'm not sure if we're ok with the idea of a QWebSettings emitting signals like this.
Comment 10 Jocelyn Turcotte 2014-02-03 03:17:14 PST
=== Bulk closing of Qt bugs ===

If you believe that this bug report is still relevant for a non-Qt port of webkit.org, please re-open it and remove [Qt] from the summary.

If you believe that this is still an important QtWebKit bug, please fill a new report at https://bugreports.qt-project.org and add a link to this issue. See http://qt-project.org/wiki/ReportingBugsInQt for additional guidelines.