Bug 553489 - Part10: reimplement setAndLoadFaviconForPage. r=sdwilsh sr=vlad

This commit is contained in:
Marco Bonardo 2010-03-25 12:34:49 +01:00
parent 208cd2f7a2
commit e831c65fee
6 changed files with 79 additions and 457 deletions

View File

@ -42,7 +42,7 @@
interface nsIURI;
interface nsIFaviconDataCallback;
[scriptable, uuid(66f6b992-e2d3-43da-ba2a-d966e34a7654)]
[scriptable, uuid(2cf188f4-3c96-4bca-b668-36b25aaf7c1d)]
interface nsIFaviconService : nsISupports
{
/**
@ -99,7 +99,8 @@ interface nsIFaviconService : nsISupports
*/
void setAndLoadFaviconForPage(in nsIURI aPageURI,
in nsIURI aFaviconURI,
in boolean aForceReload);
in boolean aForceReload,
[optional] in nsIFaviconDataCallback aCallback);
/**
* Stores the data for a given favicon URI.

View File

@ -40,9 +40,14 @@
* How to use this stepper:
*
* nsCOMPtr<AsyncFaviconStepper> stepper = new AsyncFaviconStepper(callback);
* stepper->AppendStep(new SomeStep());
* stepper->AppendStep(new SomeOtherStep());
* stepper->Start();
* stepper->SetPageURI(aPageURI);
* stepper->SetIconURI(aFaviconURI);
* rv = stepper->AppendStep(new SomeStep());
* NS_ENSURE_SUCCESS(rv, rv);
* rv = stepper->AppendStep(new SomeOtherStep());
* NS_ENSURE_SUCCESS(rv, rv);
* rv = stepper->Start();
* NS_ENSURE_SUCCESS(rv, rv);
*/
#ifndef AsyncFaviconHelpers_h_

View File

@ -49,27 +49,21 @@
*/
#include "nsFaviconService.h"
#include "nsICacheService.h"
#include "nsICacheVisitor.h"
#include "nsICachingChannel.h"
#include "nsICategoryManager.h"
#include "nsIChannelEventSink.h"
#include "nsIContentSniffer.h"
#include "nsIInterfaceRequestor.h"
#include "nsIStreamListener.h"
#include "nsISupportsPrimitives.h"
#include "nsPlacesTables.h"
#include "nsPlacesMacros.h"
#include "Helpers.h"
#include "AsyncFaviconHelpers.h"
#include "nsNavBookmarks.h"
#include "nsNavHistory.h"
#include "nsIPrefService.h"
#include "nsNetUtil.h"
#include "nsReadableUtils.h"
#include "nsStreamUtils.h"
#include "nsStringStream.h"
#include "plbase64.h"
#include "nsPlacesTables.h"
#include "nsPlacesMacros.h"
#include "nsIPrefService.h"
#include "Helpers.h"
#include "AsyncFaviconHelpers.h"
// For large favicons optimization.
#include "imgITools.h"
@ -81,8 +75,6 @@
#define MAX_FAVICON_CACHE_SIZE 256
#define FAVICON_CACHE_REDUCE_COUNT 64
#define CONTENT_SNIFFING_SERVICES "content-sniffing-services"
/**
* The maximum time we will keep a favicon around. We always ask the cache, if
* we can, but default to this value if we do not get a time back, or the time
@ -93,42 +85,10 @@
using namespace mozilla::places;
////////////////////////////////////////////////////////////////////////////////
//// Global Helpers
////////////////////////////////////////////////////////////////////////////////
//// FaviconLoadListener definition
class FaviconLoadListener : public nsIStreamListener,
public nsIInterfaceRequestor,
public nsIChannelEventSink
{
public:
FaviconLoadListener(nsIURI* aPageURI,
nsIURI* aFaviconURI,
nsIChannel* aChannel);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
private:
~FaviconLoadListener();
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIURI> mPageURI;
nsCOMPtr<nsIURI> mFaviconURI;
nsCString mData;
};
////////////////////////////////////////////////////////////////////////////////
//// ExpireFaviconsStatementCallbackNotifier definition
// Used to notify a topic to system observers on async execute completion.
// Will throw on error.
/**
* Used to notify a topic to system observers on async execute completion.
* Will throw on error.
*/
class ExpireFaviconsStatementCallbackNotifier : public AsyncStatementCallback
{
public:
@ -140,6 +100,7 @@ private:
bool* mFaviconsExpirationRunning;
};
PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsFaviconService, gFaviconService)
NS_IMPL_ISUPPORTS1(
@ -147,182 +108,6 @@ NS_IMPL_ISUPPORTS1(
, nsIFaviconService
)
namespace {
/**
* Determines the real page URI that a favicon should be stored for.
*
* @param aPageURI
* The page that is trying to load the favicon.
* @param aFaviconURI
* The URI of the favicon in question.
* @return the URI to load this favicon for, or null if this icon should not be
* loaded.
*/
already_AddRefed<nsIURI>
GetEffectivePageForFavicon(nsIURI* aPageURI, nsIURI* aFaviconURI)
{
NS_ASSERTION(aPageURI, "Must provide a pageURI!");
NS_ASSERTION(aFaviconURI, "Must provide a favicon URI!");
nsCOMPtr<nsIURI> pageURI(aPageURI);
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, nsnull);
PRBool canAddToHistory;
nsresult rv = history->CanAddURI(pageURI, &canAddToHistory);
if (NS_FAILED(rv))
return nsnull;
// If history is disabled or the page isn't addable to history, only load
// favicons if the page is bookmarked.
if (!canAddToHistory || history->IsHistoryDisabled()) {
nsNavBookmarks* bmSvc = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bmSvc, nsnull);
// Check if the page is bookmarked.
nsCOMPtr<nsIURI> bookmarkedURI;
rv = bmSvc->GetBookmarkedURIFor(aPageURI, getter_AddRefs(bookmarkedURI));
NS_ENSURE_SUCCESS(rv, nsnull);
if (!bookmarkedURI)
return nsnull;
// We always want to use the bookmark URI regardless of aPageURI.
pageURI = bookmarkedURI.forget();
}
// If we are given a URI to an image, the favicon URI will be the same as the
// page URI.
// TODO: In future we'll probably want to store a resample of the image, but
// for now we just avoid that, for database size concerns.
PRBool pageEqualsFavicon;
rv = pageURI->Equals(aFaviconURI, &pageEqualsFavicon);
NS_ENSURE_SUCCESS(rv, nsnull);
if (pageEqualsFavicon)
return nsnull;
// We don't store favicons to error pages.
nsCOMPtr<nsIURI> errorPageFaviconURI;
rv = NS_NewURI(getter_AddRefs(errorPageFaviconURI),
NS_LITERAL_CSTRING(FAVICON_ERRORPAGE_URL));
NS_ENSURE_SUCCESS(rv, nsnull);
PRBool isErrorPage;
rv = aFaviconURI->Equals(errorPageFaviconURI, &isErrorPage);
NS_ENSURE_SUCCESS(rv, nsnull);
if (isErrorPage)
return nsnull;
// This favicon should load, so return the page's URI.
return pageURI.forget();
}
/**
* This class gets the expiration data for a favicon, and starts the lookup of
* the favicon's data if it should be loaded.
*/
class FaviconExpirationGetter : public AsyncStatementCallback
{
public:
NS_DECL_ISUPPORTS
FaviconExpirationGetter(nsIURI* aPageURI,
nsIURI* aFaviconURI,
bool aForceReload) :
mPageURI(aPageURI)
, mFaviconURI(aFaviconURI)
, mForceReload(aForceReload)
, mHasData(false)
, mExpiration(0)
{
}
/**
* Performs a lookup of the needed information asynchronously, and loads the
* icon if necessary.
*/
NS_IMETHOD checkAndLoad(mozIStorageStatement* aStatement)
{
NS_ENSURE_STATE(aStatement);
mozStorageStatementScoper scoper(aStatement);
nsresult rv = BindStatementURI(aStatement, 0, mFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStoragePendingStatement> ps;
rv = aStatement->ExecuteAsync(this, getter_AddRefs(ps));
NS_ENSURE_SUCCESS(rv, rv);
// ExecuteAsync will reset the statement for us.
scoper.Abandon();
return NS_OK;
}
NS_IMETHOD HandleResult(mozIStorageResultSet* aResultSet)
{
nsCOMPtr<mozIStorageRow> row;
nsresult rv = aResultSet->GetNextRow(getter_AddRefs(row));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 dataSize = 0;
(void)row->GetInt32(1, &dataSize);
mHasData = dataSize > 0;
(void)row->GetInt64(2, &mExpiration);
return NS_OK;
}
NS_IMETHOD HandleCompletion(PRUint16 aReason)
{
if (aReason != mozIStorageStatementCallback::REASON_FINISHED)
return NS_OK;
// See if we have data and get the expiration time for this favicon. We DO
// NOT want to set the favicon for the page unless we know we have it. For
// example, if I go to random site x.com, the browser will still tell us
// that the favicon is x.com/favicon.ico even if there is no such file. We
// don't want to pollute our tables with this useless data. We also do not
// want to reload the icon if it hasn't expired yet.
if (mHasData && PR_Now() < mExpiration && !mForceReload) {
// Our data is likely still valid, but we should check to make sure the
// URI has changed, otherwise there is no need to notify.
nsFaviconService* fs = nsFaviconService::GetFaviconService();
NS_ENSURE_TRUE(fs, NS_ERROR_OUT_OF_MEMORY);
fs->checkAndNotify(mPageURI, mFaviconURI);
return NS_OK;
}
nsCOMPtr<nsIChannel> channel;
nsresult rv = NS_NewChannel(getter_AddRefs(channel), mFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener =
new FaviconLoadListener(mPageURI, mFaviconURI, channel);
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIInterfaceRequestor> listenerRequestor =
do_QueryInterface(listener, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = channel->SetNotificationCallbacks(listenerRequestor);
NS_ENSURE_SUCCESS(rv, rv);
rv = channel->AsyncOpen(listener, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
private:
nsCOMPtr<nsIURI> mPageURI;
nsCOMPtr<nsIURI> mFaviconURI;
const bool mForceReload;
bool mHasData;
PRTime mExpiration;
};
NS_IMPL_ISUPPORTS1(
FaviconExpirationGetter,
mozIStorageStatementCallback
)
} // anonymous namespace
nsFaviconService::nsFaviconService()
: mFaviconsExpirationRunning(false)
, mOptimizedIconDimension(OPTIMIZED_FAVICON_DIMENSION)
@ -693,7 +478,8 @@ nsFaviconService::SendFaviconNotifications(nsIURI* aPageURI,
NS_IMETHODIMP
nsFaviconService::SetAndLoadFaviconForPage(nsIURI* aPageURI,
nsIURI* aFaviconURI,
PRBool aForceReload)
PRBool aForceReload,
nsIFaviconDataCallback* aCallback)
{
NS_ENSURE_ARG(aPageURI);
NS_ENSURE_ARG(aFaviconURI);
@ -702,13 +488,22 @@ nsFaviconService::SetAndLoadFaviconForPage(nsIURI* aPageURI,
return NS_OK;
#ifdef LAZY_ADD
// Unfortunatly, even if DoSetAndLoadFaviconForPage is completely async,
// this method still needs to enqueue a lazy message, because in case of first
// visit to a page, the moz_places entry would not yet exists.
// So the icon has to wait for visits addition. Once visits addition will be
// async, this can go away.
nsNavHistory* historyService = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY);
return historyService->AddLazyLoadFaviconMessage(aPageURI,
aFaviconURI,
aForceReload);
aForceReload,
aCallback);
#else
return DoSetAndLoadFaviconForPage(aPageURI, aFaviconURI, aForceReload);
return DoSetAndLoadFaviconForPage(aPageURI,
aFaviconURI,
aForceReload,
aCallback);
#endif
}
@ -716,7 +511,8 @@ nsFaviconService::SetAndLoadFaviconForPage(nsIURI* aPageURI,
nsresult
nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPageURI,
nsIURI* aFaviconURI,
PRBool aForceReload)
PRBool aForceReload,
nsIFaviconDataCallback* aCallback)
{
if (mFaviconsExpirationRunning)
return NS_OK;
@ -728,21 +524,30 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPageURI,
NS_ENSURE_SUCCESS(rv, rv);
if (previouslyFailed) {
if (aForceReload)
RemoveFailedFavicon(aFaviconURI); // force reload clears from failed cache
RemoveFailedFavicon(aFaviconURI);
else
return NS_OK; // ignore previously failed favicons
return NS_OK;
}
// Get the URI we should load this favicon for. If we don't get any URI, then
// we don't want to save this favicon, so we early return.
nsCOMPtr<nsIURI> page = GetEffectivePageForFavicon(aPageURI, aFaviconURI);
NS_ENSURE_TRUE(page, NS_OK);
nsRefPtr<FaviconExpirationGetter> dataGetter =
new FaviconExpirationGetter(page, aFaviconURI, !!aForceReload);
NS_ENSURE_TRUE(dataGetter, NS_ERROR_OUT_OF_MEMORY);
rv = dataGetter->checkAndLoad(GetStatement(mDBGetIconInfo));
nsCOMPtr<AsyncFaviconStepper> stepper = new AsyncFaviconStepper(aCallback);
stepper->SetPageURI(aPageURI);
stepper->SetIconURI(aFaviconURI);
rv = stepper->AppendStep(new GetEffectivePageStep());
NS_ENSURE_SUCCESS(rv, rv);
rv = stepper->AppendStep(new FetchDatabaseIconStep());
NS_ENSURE_SUCCESS(rv, rv);
rv = stepper->AppendStep(new EnsureDatabaseEntryStep());
NS_ENSURE_SUCCESS(rv, rv);
rv = stepper->AppendStep(new FetchNetworkIconStep(
aForceReload ? FETCH_ALWAYS : FETCH_IF_MISSING));
NS_ENSURE_SUCCESS(rv, rv);
rv = stepper->AppendStep(new SetFaviconDataStep());
NS_ENSURE_SUCCESS(rv, rv);
rv = stepper->AppendStep(new AssociateIconWithPageStep());
NS_ENSURE_SUCCESS(rv, rv);
rv = stepper->AppendStep(new NotifyStep());
NS_ENSURE_SUCCESS(rv, rv);
rv = stepper->Start();
NS_ENSURE_SUCCESS(rv, rv);
// DB will be updated and observers notified when data has finished loading.
@ -1229,202 +1034,6 @@ nsFaviconService::GetFaviconDataAsync(nsIURI* aFaviconURI,
return stmt->ExecuteAsync(aCallback, getter_AddRefs(pendingStatement));
}
void
nsFaviconService::checkAndNotify(nsIURI *aPageURI,
nsIURI *aFaviconURI)
{
// For page revisits (pretty common) we DON'T want to send out any
// notifications if we've already set the favicon. These notifications will
// cause parts of the UI to update and will be slow. This also saves us a
// database write in these cases.
nsCOMPtr<nsIURI> oldFavicon;
PRBool faviconsEqual;
if (NS_SUCCEEDED(GetFaviconForPage(aPageURI, getter_AddRefs(oldFavicon))) &&
NS_SUCCEEDED(aFaviconURI->Equals(oldFavicon, &faviconsEqual)) &&
faviconsEqual)
return; // already set
// This will associate the favicon URL with the page.
PRBool hasData;
nsresult rv = SetFaviconUrlForPageInternal(aPageURI, aFaviconURI, &hasData);
if (NS_FAILED(rv))
return;
if (hasData) {
SendFaviconNotifications(aPageURI, aFaviconURI);
UpdateBookmarkRedirectFavicon(aPageURI, aFaviconURI);
}
}
////////////////////////////////////////////////////////////////////////////////
//// FaviconLoadListener
NS_IMPL_ISUPPORTS4(FaviconLoadListener,
nsIRequestObserver,
nsIStreamListener,
nsIInterfaceRequestor,
nsIChannelEventSink)
FaviconLoadListener::FaviconLoadListener(nsIURI* aPageURI,
nsIURI* aFaviconURI,
nsIChannel* aChannel) :
mChannel(aChannel),
mPageURI(aPageURI),
mFaviconURI(aFaviconURI)
{
}
FaviconLoadListener::~FaviconLoadListener()
{
}
NS_IMETHODIMP
FaviconLoadListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
{
return NS_OK;
}
NS_IMETHODIMP
FaviconLoadListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
nsresult aStatusCode)
{
nsFaviconService *fs = nsFaviconService::GetFaviconService();
NS_ENSURE_TRUE(fs, NS_ERROR_OUT_OF_MEMORY);
if (NS_FAILED(aStatusCode) || mData.Length() == 0) {
// load failed, add to failed cache
fs->AddFailedFavicon(mFaviconURI);
return NS_OK;
}
// sniff the MIME type
nsresult rv;
nsCOMPtr<nsICategoryManager> categoryManager =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISimpleEnumerator> sniffers;
rv = categoryManager->EnumerateCategory(CONTENT_SNIFFING_SERVICES,
getter_AddRefs(sniffers));
NS_ENSURE_SUCCESS(rv, rv);
nsCString mimeType;
PRBool hasMore = PR_FALSE;
while (mimeType.IsEmpty() && NS_SUCCEEDED(sniffers->HasMoreElements(&hasMore))
&& hasMore) {
nsCOMPtr<nsISupports> snifferCIDSupports;
rv = sniffers->GetNext(getter_AddRefs(snifferCIDSupports));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsCString> snifferCIDSupportsCString =
do_QueryInterface(snifferCIDSupports, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString snifferCID;
rv = snifferCIDSupportsCString->GetData(snifferCID);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContentSniffer> sniffer = do_GetService(snifferCID.get(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
sniffer->GetMIMETypeFromContent(
aRequest,
reinterpret_cast<PRUint8*>(const_cast<char*>(mData.get())),
mData.Length(), mimeType);
// ignore errors: mime type will be left empty and we'll try the next sniffer
}
if (mimeType.IsEmpty()) {
// we can not handle favicons that do not have a recognisable MIME type
fs->AddFailedFavicon(mFaviconURI);
return NS_OK;
}
// Attempt to get an expiration time from the cache. If this fails, we'll
// make one up.
PRTime expiration = -1;
nsCOMPtr<nsICachingChannel> cachingChannel(do_QueryInterface(mChannel));
if (cachingChannel) {
nsCOMPtr<nsISupports> cacheToken;
rv = cachingChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsICacheEntryInfo> cacheEntry(do_QueryInterface(cacheToken));
PRUint32 seconds;
rv = cacheEntry->GetExpirationTime(&seconds);
if (NS_SUCCEEDED(rv)) {
// Set the expiration, but make sure we honor our cap.
expiration = PR_Now() + NS_MIN((PRTime)seconds * PR_USEC_PER_SEC,
MAX_FAVICON_EXPIRATION);
}
}
}
// If we did not obtain a time from the cache, or it was negative, use our cap
if (expiration < 0)
expiration = PR_Now() + MAX_FAVICON_EXPIRATION;
mozStorageTransaction transaction(fs->mDBConn, PR_FALSE);
// save the favicon data
// This could fail if the favicon is bigger than defined limit, in such a
// case data will not be saved to the db but we will still continue.
(void)fs->SetFaviconData(mFaviconURI,
reinterpret_cast<PRUint8*>(const_cast<char*>(mData.get())),
mData.Length(), mimeType, expiration);
// set the favicon for the page
PRBool hasData;
rv = fs->SetFaviconUrlForPageInternal(mPageURI, mFaviconURI,
&hasData);
NS_ENSURE_SUCCESS(rv, rv);
fs->UpdateBookmarkRedirectFavicon(mPageURI, mFaviconURI);
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
fs->SendFaviconNotifications(mPageURI, mFaviconURI);
return NS_OK;
}
NS_IMETHODIMP
FaviconLoadListener::OnDataAvailable(nsIRequest* aRequest,
nsISupports* aContext,
nsIInputStream* aInputStream,
PRUint32 aOffset,
PRUint32 aCount)
{
nsCString buffer;
nsresult rv = NS_ConsumeStream(aInputStream, aCount, buffer);
if (rv != NS_BASE_STREAM_WOULD_BLOCK && NS_FAILED(rv))
return rv;
mData.Append(buffer);
return NS_OK;
}
NS_IMETHODIMP
FaviconLoadListener::GetInterface(const nsIID& uuid, void** aResult)
{
return QueryInterface(uuid, aResult);
}
NS_IMETHODIMP
FaviconLoadListener::OnChannelRedirect(nsIChannel* oldChannel,
nsIChannel* newChannel,
PRUint32 flags)
{
mChannel = newChannel;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// ExpireFaviconsStatementCallbackNotifier

View File

@ -106,8 +106,10 @@ public:
}
// internal version called by history when done lazily
nsresult DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon,
PRBool aForceReload);
nsresult DoSetAndLoadFaviconForPage(nsIURI* aPageURI,
nsIURI* aFaviconURI,
PRBool aForceReload,
nsIFaviconDataCallback* aCallback);
// addition to API for strings to prevent excessive parsing of URIs
nsresult GetFaviconLinkForIconString(const nsCString& aIcon, nsIURI** aOutput);

View File

@ -5924,18 +5924,19 @@ nsNavHistory::DecayFrecency()
#ifdef LAZY_ADD
// nsNavHistory::AddLazyLoadFaviconMessage
nsresult
nsNavHistory::AddLazyLoadFaviconMessage(nsIURI* aPage, nsIURI* aFavicon,
PRBool aForceReload)
nsNavHistory::AddLazyLoadFaviconMessage(nsIURI* aPageURI,
nsIURI* aFaviconURI,
PRBool aForceReload,
nsIFaviconDataCallback* aCallback)
{
LazyMessage message;
nsresult rv = message.Init(LazyMessage::Type_Favicon, aPage);
nsresult rv = message.Init(LazyMessage::Type_Favicon, aPageURI);
NS_ENSURE_SUCCESS(rv, rv);
rv = aFavicon->Clone(getter_AddRefs(message.favicon));
rv = aFaviconURI->Clone(getter_AddRefs(message.favicon));
NS_ENSURE_SUCCESS(rv, rv);
message.alwaysLoadFavicon = aForceReload;
message.callback = aCallback;
return AddLazyMessage(message);
}
@ -6024,7 +6025,8 @@ nsNavHistory::CommitLazyMessages(PRBool aIsShutdown)
if (faviconService) {
faviconService->DoSetAndLoadFaviconForPage(message.uri,
message.favicon,
message.alwaysLoadFavicon);
message.alwaysLoadFavicon,
message.callback);
}
break;
}

View File

@ -64,7 +64,7 @@
#include "nsINavBookmarksService.h"
#include "nsIPrivateBrowsingService.h"
#include "nsIFaviconService.h"
#include "nsNavHistoryResult.h"
#include "nsNavHistoryQuery.h"
@ -168,8 +168,10 @@ public:
* Adds a lazy message for adding a favicon. Used by the favicon service so
* that favicons are handled lazily just like page adds.
*/
nsresult AddLazyLoadFaviconMessage(nsIURI* aPage, nsIURI* aFavicon,
PRBool aForceReload);
nsresult AddLazyLoadFaviconMessage(nsIURI* aPageURI,
nsIURI* aFaviconURI,
PRBool aForceReload,
nsIFaviconDataCallback* aCallback);
#endif
/**
@ -587,6 +589,7 @@ protected:
// valid when type == LAZY_FAVICON
nsCOMPtr<nsIURI> favicon;
PRBool alwaysLoadFavicon;
nsCOMPtr<nsIFaviconDataCallback> callback;
};
nsTArray<LazyMessage> mLazyMessages;
nsCOMPtr<nsITimer> mLazyTimer;