mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 553489 - Part10: reimplement setAndLoadFaviconForPage. r=sdwilsh sr=vlad
This commit is contained in:
parent
208cd2f7a2
commit
e831c65fee
@ -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.
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user