Bug 1269737 - Make AsyncFaviconHelpers more maintainable. r=adw

MozReview-Commit-ID: l0GnzPZK8w

--HG--
rename : toolkit/components/places/AsyncFaviconHelpers.cpp => toolkit/components/places/FaviconHelpers.cpp
rename : toolkit/components/places/AsyncFaviconHelpers.h => toolkit/components/places/FaviconHelpers.h
extra : rebase_source : d164e8d246ee66b555bbd7d4db0d552da5ff2b28
This commit is contained in:
Marco Bonardo 2016-05-06 11:37:26 +02:00
Родитель 6290ac73e4
Коммит 817566c802
5 изменённых файлов: 150 добавлений и 379 удалений

Просмотреть файл

@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AsyncFaviconHelpers.h"
#include "FaviconHelpers.h"
#include "nsICacheEntry.h"
#include "nsICachingChannel.h"
@ -40,12 +40,11 @@ namespace {
* Page that should be fetched.
*/
nsresult
FetchPageInfo(RefPtr<Database>& aDB,
FetchPageInfo(const RefPtr<Database>& aDB,
PageData& _page)
{
NS_PRECONDITION(_page.spec.Length(), "Must have a non-empty spec!");
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread");
MOZ_ASSERT(_page.spec.Length(), "Must have a non-empty spec!");
MOZ_ASSERT(!NS_IsMainThread());
// This query finds the bookmarked uri we want to set the icon for,
// walking up to two redirect levels.
@ -139,11 +138,10 @@ FetchPageInfo(RefPtr<Database>& aDB,
* Icon that should be stored.
*/
nsresult
SetIconInfo(RefPtr<Database>& aDB,
IconData& aIcon)
SetIconInfo(const RefPtr<Database>& aDB,
const IconData& aIcon)
{
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread");
MOZ_ASSERT(!NS_IsMainThread());
nsCOMPtr<mozIStorageStatement> stmt = aDB->GetStatement(
"INSERT OR REPLACE INTO moz_favicons "
@ -178,12 +176,11 @@ SetIconInfo(RefPtr<Database>& aDB,
* Icon that should be fetched.
*/
nsresult
FetchIconInfo(RefPtr<Database>& aDB,
FetchIconInfo(const RefPtr<Database>& aDB,
IconData& _icon)
{
NS_PRECONDITION(_icon.spec.Length(), "Must have a non-empty spec!");
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread");
MOZ_ASSERT(_icon.spec.Length(), "Must have a non-empty spec!");
MOZ_ASSERT(!NS_IsMainThread());
if (_icon.status & ICON_STATUS_CACHED) {
return NS_OK;
@ -238,13 +235,12 @@ FetchIconInfo(RefPtr<Database>& aDB,
}
nsresult
FetchIconURL(RefPtr<Database>& aDB,
FetchIconURL(const RefPtr<Database>& aDB,
const nsACString& aPageSpec,
nsACString& aIconSpec)
{
NS_PRECONDITION(!aPageSpec.IsEmpty(), "Page spec must not be empty.");
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread.");
MOZ_ASSERT(!aPageSpec.IsEmpty(), "Page spec must not be empty.");
MOZ_ASSERT(!NS_IsMainThread());
aIconSpec.Truncate();
@ -280,8 +276,7 @@ FetchIconURL(RefPtr<Database>& aDB,
PRTime
GetExpirationTimeFromChannel(nsIChannel* aChannel)
{
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread");
MOZ_ASSERT(NS_IsMainThread());
// Attempt to get an expiration time from the cache. If this fails, we'll
// make one up.
@ -320,8 +315,7 @@ nsresult
OptimizeIconSize(IconData& aIcon,
nsFaviconService* aFaviconSvc)
{
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread");
MOZ_ASSERT(NS_IsMainThread());
// Even if the page provides a large image for the favicon (eg, a highres
// image or a multiresolution .ico file), don't try to store more data than
@ -343,25 +337,6 @@ OptimizeIconSize(IconData& aIcon,
} // namespace
////////////////////////////////////////////////////////////////////////////////
//// AsyncFaviconHelperBase
AsyncFaviconHelperBase::AsyncFaviconHelperBase(
nsCOMPtr<nsIFaviconDataCallback>& aCallback
)
{
// Don't AddRef or Release in runnables for thread-safety.
mCallback.swap(aCallback);
}
AsyncFaviconHelperBase::~AsyncFaviconHelperBase()
{
if (mCallback) {
NS_ReleaseOnMainThread(mCallback.forget(), true);
}
}
////////////////////////////////////////////////////////////////////////////////
//// AsyncFetchAndSetIconForPage
@ -374,95 +349,26 @@ NS_IMPL_ISUPPORTS_INHERITED(
, mozIPlacesPendingOperation
)
// static
nsresult
AsyncFetchAndSetIconForPage::start(nsIURI* aFaviconURI,
nsIURI* aPageURI,
enum AsyncFaviconFetchMode aFetchMode,
bool aFaviconLoadPrivate,
nsIFaviconDataCallback* aCallback,
nsIPrincipal* aLoadingPrincipal,
mozIPlacesPendingOperation** _canceler)
{
NS_ENSURE_ARG(aLoadingPrincipal);
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread");
PageData page;
nsresult rv = aPageURI->GetSpec(page.spec);
NS_ENSURE_SUCCESS(rv, rv);
// URIs can arguably miss a host.
(void)GetReversedHostname(aPageURI, page.revHost);
bool canAddToHistory;
nsNavHistory* navHistory = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(navHistory, NS_ERROR_OUT_OF_MEMORY);
rv = navHistory->CanAddURI(aPageURI, &canAddToHistory);
NS_ENSURE_SUCCESS(rv, rv);
page.canAddToHistory = !!canAddToHistory && !aFaviconLoadPrivate;
IconData icon;
nsFaviconService* favicons = nsFaviconService::GetFaviconService();
NS_ENSURE_STATE(favicons);
UnassociatedIconHashKey* iconKey =
favicons->mUnassociatedIcons.GetEntry(aFaviconURI);
if (iconKey) {
icon = iconKey->iconData;
favicons->mUnassociatedIcons.RemoveEntry(iconKey);
} else {
icon.fetchMode = aFetchMode;
rv = aFaviconURI->GetSpec(icon.spec);
NS_ENSURE_SUCCESS(rv, rv);
}
// If the page url points to an image, the icon's url will be the same.
// In future evaluate to store a resample of the image. For now avoid that
// for database size concerns.
// Don't store favicons for error pages too.
if (icon.spec.Equals(page.spec) ||
icon.spec.Equals(FAVICON_ERRORPAGE_URL)) {
return NS_OK;
}
// The event will swap owning pointers, thus we need a new pointer.
nsCOMPtr<nsIFaviconDataCallback> callback(aCallback);
RefPtr<AsyncFetchAndSetIconForPage> event =
new AsyncFetchAndSetIconForPage(icon, page, aFaviconLoadPrivate,
callback, aLoadingPrincipal);
// Get the target thread and start the work.
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
// Return this event to the caller to allow aborting an eventual fetch.
event.forget(_canceler);
return NS_OK;
}
AsyncFetchAndSetIconForPage::AsyncFetchAndSetIconForPage(
IconData& aIcon
, PageData& aPage
, bool aFaviconLoadPrivate
, nsCOMPtr<nsIFaviconDataCallback>& aCallback
, nsIFaviconDataCallback* aCallback
, nsIPrincipal* aLoadingPrincipal
) : AsyncFaviconHelperBase(aCallback)
) : mCallback(new nsMainThreadPtrHolder<nsIFaviconDataCallback>(aCallback))
, mIcon(aIcon)
, mPage(aPage)
, mFaviconLoadPrivate(aFaviconLoadPrivate)
, mLoadingPrincipal(new nsMainThreadPtrHolder<nsIPrincipal>(aLoadingPrincipal))
, mCanceled(false)
{
MOZ_ASSERT(NS_IsMainThread());
}
NS_IMETHODIMP
AsyncFetchAndSetIconForPage::Run()
{
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread");
MOZ_ASSERT(!NS_IsMainThread());
// Try to fetch the icon from the database.
RefPtr<Database> DB = Database::GetDatabase();
@ -591,7 +497,7 @@ AsyncFetchAndSetIconForPage::OnDataAvailable(nsIRequest* aRequest,
NS_IMETHODIMP
AsyncFetchAndSetIconForPage::GetInterface(const nsIID& uuid,
void** aResult)
void** aResult)
{
return QueryInterface(uuid, aResult);
}
@ -715,24 +621,19 @@ AsyncFetchAndSetIconForPage::OnStopRequest(nsIRequest* aRequest,
//// AsyncAssociateIconToPage
AsyncAssociateIconToPage::AsyncAssociateIconToPage(
IconData& aIcon
, PageData& aPage
, nsCOMPtr<nsIFaviconDataCallback>& aCallback
) : AsyncFaviconHelperBase(aCallback)
const IconData& aIcon
, const PageData& aPage
, const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback
) : mCallback(aCallback)
, mIcon(aIcon)
, mPage(aPage)
{
}
AsyncAssociateIconToPage::~AsyncAssociateIconToPage()
{
}
NS_IMETHODIMP
AsyncAssociateIconToPage::Run()
{
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread");
MOZ_ASSERT(!NS_IsMainThread());
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
@ -814,48 +715,19 @@ AsyncAssociateIconToPage::Run()
////////////////////////////////////////////////////////////////////////////////
//// AsyncGetFaviconURLForPage
// static
nsresult
AsyncGetFaviconURLForPage::start(nsIURI* aPageURI,
nsIFaviconDataCallback* aCallback)
{
NS_ENSURE_ARG(aCallback);
NS_ENSURE_ARG(aPageURI);
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread.");
nsAutoCString pageSpec;
nsresult rv = aPageURI->GetSpec(pageSpec);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFaviconDataCallback> callback = aCallback;
RefPtr<AsyncGetFaviconURLForPage> event =
new AsyncGetFaviconURLForPage(pageSpec, callback);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
return NS_OK;
}
AsyncGetFaviconURLForPage::AsyncGetFaviconURLForPage(
const nsACString& aPageSpec
, nsCOMPtr<nsIFaviconDataCallback>& aCallback
) : AsyncFaviconHelperBase(aCallback)
, nsIFaviconDataCallback* aCallback
) : mCallback(new nsMainThreadPtrHolder<nsIFaviconDataCallback>(aCallback))
{
MOZ_ASSERT(NS_IsMainThread());
mPageSpec.Assign(aPageSpec);
}
AsyncGetFaviconURLForPage::~AsyncGetFaviconURLForPage()
{
}
NS_IMETHODIMP
AsyncGetFaviconURLForPage::Run()
{
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread.");
MOZ_ASSERT(!NS_IsMainThread());
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
@ -881,48 +753,19 @@ AsyncGetFaviconURLForPage::Run()
////////////////////////////////////////////////////////////////////////////////
//// AsyncGetFaviconDataForPage
// static
nsresult
AsyncGetFaviconDataForPage::start(nsIURI* aPageURI,
nsIFaviconDataCallback* aCallback)
{
NS_ENSURE_ARG(aCallback);
NS_ENSURE_ARG(aPageURI);
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread.");
nsAutoCString pageSpec;
nsresult rv = aPageURI->GetSpec(pageSpec);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFaviconDataCallback> callback = aCallback;
RefPtr<AsyncGetFaviconDataForPage> event =
new AsyncGetFaviconDataForPage(pageSpec, callback);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
return NS_OK;
}
AsyncGetFaviconDataForPage::AsyncGetFaviconDataForPage(
const nsACString& aPageSpec
, nsCOMPtr<nsIFaviconDataCallback>& aCallback
) : AsyncFaviconHelperBase(aCallback)
{
, nsIFaviconDataCallback* aCallback
) : mCallback(new nsMainThreadPtrHolder<nsIFaviconDataCallback>(aCallback))
{
MOZ_ASSERT(NS_IsMainThread());
mPageSpec.Assign(aPageSpec);
}
AsyncGetFaviconDataForPage::~AsyncGetFaviconDataForPage()
{
}
NS_IMETHODIMP
AsyncGetFaviconDataForPage::Run()
{
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread.");
MOZ_ASSERT(!NS_IsMainThread());
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
@ -953,42 +796,15 @@ AsyncGetFaviconDataForPage::Run()
////////////////////////////////////////////////////////////////////////////////
//// AsyncReplaceFaviconData
// static
nsresult
AsyncReplaceFaviconData::start(IconData *aIcon)
{
NS_ENSURE_ARG(aIcon);
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread.");
nsCOMPtr<nsIFaviconDataCallback> callback;
RefPtr<AsyncReplaceFaviconData> event =
new AsyncReplaceFaviconData(*aIcon, callback);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
return NS_OK;
}
AsyncReplaceFaviconData::AsyncReplaceFaviconData(
IconData &aIcon
, nsCOMPtr<nsIFaviconDataCallback>& aCallback
) : AsyncFaviconHelperBase(aCallback)
, mIcon(aIcon)
{
}
AsyncReplaceFaviconData::~AsyncReplaceFaviconData()
AsyncReplaceFaviconData::AsyncReplaceFaviconData(const IconData &aIcon)
: mIcon(aIcon)
{
}
NS_IMETHODIMP
AsyncReplaceFaviconData::Run()
{
NS_PRECONDITION(!NS_IsMainThread(),
"This should not be called on the main thread");
MOZ_ASSERT(!NS_IsMainThread());
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
@ -1005,35 +821,18 @@ AsyncReplaceFaviconData::Run()
NS_ENSURE_SUCCESS(rv, rv);
// We can invalidate the cache version since we now persist the icon.
nsCOMPtr<nsIRunnable> event = new RemoveIconDataCacheEntry(mIcon, mCallback);
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod(this, &AsyncReplaceFaviconData::RemoveIconDataCacheEntry);
rv = NS_DispatchToMainThread(event);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// RemoveIconDataCacheEntry
RemoveIconDataCacheEntry::RemoveIconDataCacheEntry(
IconData& aIcon
, nsCOMPtr<nsIFaviconDataCallback>& aCallback
)
: AsyncFaviconHelperBase(aCallback)
, mIcon(aIcon)
nsresult
AsyncReplaceFaviconData::RemoveIconDataCacheEntry()
{
}
RemoveIconDataCacheEntry::~RemoveIconDataCacheEntry()
{
}
NS_IMETHODIMP
RemoveIconDataCacheEntry::Run()
{
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread");
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIURI> iconURI;
nsresult rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
@ -1051,25 +850,20 @@ RemoveIconDataCacheEntry::Run()
//// NotifyIconObservers
NotifyIconObservers::NotifyIconObservers(
IconData& aIcon
, PageData& aPage
, nsCOMPtr<nsIFaviconDataCallback>& aCallback
const IconData& aIcon
, const PageData& aPage
, const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback
)
: AsyncFaviconHelperBase(aCallback)
: mCallback(aCallback)
, mIcon(aIcon)
, mPage(aPage)
{
}
NotifyIconObservers::~NotifyIconObservers()
{
}
NS_IMETHODIMP
NotifyIconObservers::Run()
{
NS_PRECONDITION(NS_IsMainThread(),
"This should be called on the main thread");
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIURI> iconURI;
if (!mIcon.spec.IsEmpty()) {
@ -1117,7 +911,7 @@ NotifyIconObservers::SendGlobalNotifications(nsIURI* aIconURI)
if (!DB)
return;
// This will be silent, so be sure to not pass in the current callback.
nsCOMPtr<nsIFaviconDataCallback> nullCallback;
nsMainThreadPtrHandle<nsIFaviconDataCallback> nullCallback;
RefPtr<AsyncAssociateIconToPage> event =
new AsyncAssociateIconToPage(mIcon, bookmarkedPage, nullCallback);
DB->DispatchToAsyncThread(event);

Просмотреть файл

@ -4,8 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AsyncFaviconHelpers_h_
#define AsyncFaviconHelpers_h_
#pragma once
#include "nsIFaviconService.h"
#include "nsIChannelEventSink.h"
@ -95,65 +94,25 @@ struct PageData
nsCString guid;
};
/**
* Base class for events declared in this file. This class's main purpose is
* to declare a destructor which releases mCallback on the main thread.
*/
class AsyncFaviconHelperBase : public Runnable
{
protected:
explicit AsyncFaviconHelperBase(nsCOMPtr<nsIFaviconDataCallback>& aCallback);
virtual ~AsyncFaviconHelperBase();
// Strong reference since we are responsible for its existence.
nsCOMPtr<nsIFaviconDataCallback> mCallback;
};
/**
* Async fetches icon from database or network, associates it with the required
* page and finally notifies the change.
*/
class AsyncFetchAndSetIconForPage final : public AsyncFaviconHelperBase
class AsyncFetchAndSetIconForPage final : public Runnable
, public nsIStreamListener
, public nsIInterfaceRequestor
, public nsIChannelEventSink
, public mozIPlacesPendingOperation
{
public:
NS_DECL_NSIRUNNABLE
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSIRUNNABLE
NS_DECL_MOZIPLACESPENDINGOPERATION
NS_DECL_ISUPPORTS_INHERITED
/**
* Creates the event and dispatches it to the async thread.
*
* @param aFaviconURI
* URI of the icon to be fetched and associated.
* @param aPageURI
* URI of the page to which associate the icon.
* @param aFetchMode
* Specifies whether a icon should be fetched from network if not found
* in the database.
* @param aFaviconLoadPrivate
* Whether this favicon load is in private browsing.
* @param aCallback
* Function to be called when the fetch-and-associate process finishes.
* @param aLoadingPrincipal
* LoadingPrincipal of the icon to be fetched.
*/
static nsresult start(nsIURI* aFaviconURI,
nsIURI* aPageURI,
enum AsyncFaviconFetchMode aFetchMode,
bool aFaviconLoadPrivate,
nsIFaviconDataCallback* aCallback,
nsIPrincipal* aLoadingPrincipal,
mozIPlacesPendingOperation ** _canceler);
/**
* Constructor.
*
@ -171,13 +130,14 @@ class AsyncFetchAndSetIconForPage final : public AsyncFaviconHelperBase
AsyncFetchAndSetIconForPage(IconData& aIcon,
PageData& aPage,
bool aFaviconLoadPrivate,
nsCOMPtr<nsIFaviconDataCallback>& aCallback,
nsIFaviconDataCallback* aCallback,
nsIPrincipal* aLoadingPrincipal);
private:
nsresult FetchFromNetwork();
virtual ~AsyncFetchAndSetIconForPage() {}
nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
IconData mIcon;
PageData mPage;
const bool mFaviconLoadPrivate;
@ -190,7 +150,7 @@ private:
* Associates the icon to the required page, finally dispatches an event to the
* main thread to notify the change to observers.
*/
class AsyncAssociateIconToPage : public AsyncFaviconHelperBase
class AsyncAssociateIconToPage final : public Runnable
{
public:
NS_DECL_NSIRUNNABLE
@ -205,13 +165,12 @@ public:
* @param aCallback
* Function to be called when the associate process finishes.
*/
AsyncAssociateIconToPage(IconData& aIcon,
PageData& aPage,
nsCOMPtr<nsIFaviconDataCallback>& aCallback);
AsyncAssociateIconToPage(const IconData& aIcon,
const PageData& aPage,
const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback);
virtual ~AsyncAssociateIconToPage();
protected:
private:
nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
IconData mIcon;
PageData mPage;
};
@ -220,22 +179,11 @@ protected:
* Asynchronously tries to get the URL of a page's favicon, then notifies the
* given observer.
*/
class AsyncGetFaviconURLForPage : public AsyncFaviconHelperBase
class AsyncGetFaviconURLForPage final : public Runnable
{
public:
NS_DECL_NSIRUNNABLE
/**
* Creates the event and dispatches it to the I/O thread.
*
* @param aPageURI
* URL of the page whose favicon's URL we're fetching
* @param aCallback
* function to be called once finished
*/
static nsresult start(nsIURI* aPageURI,
nsIFaviconDataCallback* aCallback);
/**
* Constructor.
*
@ -245,11 +193,10 @@ public:
* function to be called once finished
*/
AsyncGetFaviconURLForPage(const nsACString& aPageSpec,
nsCOMPtr<nsIFaviconDataCallback>& aCallback);
virtual ~AsyncGetFaviconURLForPage();
nsIFaviconDataCallback* aCallback);
private:
nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
nsCString mPageSpec;
};
@ -258,22 +205,11 @@ private:
* Asynchronously tries to get the URL and data of a page's favicon, then
* notifies the given observer.
*/
class AsyncGetFaviconDataForPage : public AsyncFaviconHelperBase
class AsyncGetFaviconDataForPage final : public Runnable
{
public:
NS_DECL_NSIRUNNABLE
/**
* Creates the event and dispatches it to the I/O thread.
*
* @param aPageURI
* URL of the page whose favicon URL and data we're fetching
* @param aCallback
* function to be called once finished
*/
static nsresult start(nsIURI* aPageURI,
nsIFaviconDataCallback* aCallback);
/**
* Constructor.
*
@ -283,47 +219,30 @@ public:
* function to be called once finished
*/
AsyncGetFaviconDataForPage(const nsACString& aPageSpec,
nsCOMPtr<nsIFaviconDataCallback>& aCallback);
virtual ~AsyncGetFaviconDataForPage();
nsIFaviconDataCallback* aCallback);
private:
nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
nsCString mPageSpec;
};
class AsyncReplaceFaviconData : public AsyncFaviconHelperBase
class AsyncReplaceFaviconData final : public Runnable
{
public:
NS_DECL_NSIRUNNABLE
static nsresult start(IconData *aIcon);
explicit AsyncReplaceFaviconData(const IconData& aIcon);
AsyncReplaceFaviconData(IconData &aIcon,
nsCOMPtr<nsIFaviconDataCallback>& aCallback);
private:
nsresult RemoveIconDataCacheEntry();
virtual ~AsyncReplaceFaviconData();
protected:
IconData mIcon;
};
class RemoveIconDataCacheEntry : public AsyncFaviconHelperBase
{
public:
NS_DECL_NSIRUNNABLE
RemoveIconDataCacheEntry(IconData &aIcon,
nsCOMPtr<nsIFaviconDataCallback>& aCallback);
virtual ~RemoveIconDataCacheEntry();
protected:
IconData mIcon;
};
/**
* Notifies the icon change to favicon observers.
*/
class NotifyIconObservers : public AsyncFaviconHelperBase
class NotifyIconObservers final : public Runnable
{
public:
NS_DECL_NSIRUNNABLE
@ -338,12 +257,12 @@ public:
* @param aCallback
* Function to be notified in all cases.
*/
NotifyIconObservers(IconData& aIcon,
PageData& aPage,
nsCOMPtr<nsIFaviconDataCallback>& aCallback);
virtual ~NotifyIconObservers();
NotifyIconObservers(const IconData& aIcon,
const PageData& aPage,
const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback);
protected:
private:
nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
IconData mIcon;
PageData mPage;
@ -352,5 +271,3 @@ protected:
} // namespace places
} // namespace mozilla
#endif // AsyncFaviconHelpers_h_

Просмотреть файл

@ -35,8 +35,8 @@ if CONFIG['MOZ_PLACES']:
]
UNIFIED_SOURCES += [
'AsyncFaviconHelpers.cpp',
'Database.cpp',
'FaviconHelpers.cpp',
'Helpers.cpp',
'History.cpp',
'nsAnnoProtocolHandler.cpp',

Просмотреть файл

@ -18,7 +18,6 @@
#include "nsNavHistory.h"
#include "nsPlacesMacros.h"
#include "Helpers.h"
#include "AsyncFaviconHelpers.h"
#include "nsNetUtil.h"
#include "nsReadableUtils.h"
@ -215,6 +214,7 @@ nsFaviconService::SetAndFetchFaviconForPage(nsIURI* aPageURI,
nsIPrincipal* aLoadingPrincipal,
mozIPlacesPendingOperation **_canceler)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aPageURI);
NS_ENSURE_ARG(aFaviconURI);
NS_ENSURE_ARG_POINTER(_canceler);
@ -242,13 +242,52 @@ nsFaviconService::SetAndFetchFaviconForPage(nsIURI* aPageURI,
// Check if the icon already exists and fetch it from the network, if needed.
// Finally associate the icon to the requested page if not yet associated.
bool loadPrivate = aFaviconLoadType == nsIFaviconService::FAVICON_LOAD_PRIVATE;
rv = AsyncFetchAndSetIconForPage::start(
aFaviconURI, aPageURI, aForceReload ? FETCH_ALWAYS : FETCH_IF_MISSING,
loadPrivate, aCallback, loadingPrincipal, _canceler
);
NS_ENSURE_SUCCESS(rv, rv);
PageData page;
rv = aPageURI->GetSpec(page.spec);
NS_ENSURE_SUCCESS(rv, rv);
// URIs can arguably miss a host.
(void)GetReversedHostname(aPageURI, page.revHost);
bool canAddToHistory;
nsNavHistory* navHistory = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(navHistory, NS_ERROR_OUT_OF_MEMORY);
rv = navHistory->CanAddURI(aPageURI, &canAddToHistory);
NS_ENSURE_SUCCESS(rv, rv);
page.canAddToHistory = !!canAddToHistory && !loadPrivate;
IconData icon;
UnassociatedIconHashKey* iconKey = mUnassociatedIcons.GetEntry(aFaviconURI);
if (iconKey) {
icon = iconKey->iconData;
mUnassociatedIcons.RemoveEntry(iconKey);
} else {
icon.fetchMode = aForceReload ? FETCH_ALWAYS : FETCH_IF_MISSING;
rv = aFaviconURI->GetSpec(icon.spec);
NS_ENSURE_SUCCESS(rv, rv);
}
// If the page url points to an image, the icon's url will be the same.
// In future evaluate to store a resample of the image. For now avoid that
// for database size concerns.
// Don't store favicons for error pages too.
if (icon.spec.Equals(page.spec) ||
icon.spec.Equals(FAVICON_ERRORPAGE_URL)) {
return NS_OK;
}
RefPtr<AsyncFetchAndSetIconForPage> event =
new AsyncFetchAndSetIconForPage(icon, page, loadPrivate,
aCallback, aLoadingPrincipal);
// Get the target thread and start the work.
// DB will be updated and observers notified when data has finished loading.
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
// Return this event to the caller to allow aborting an eventual fetch.
event.forget(_canceler);
return NS_OK;
}
@ -259,6 +298,7 @@ nsFaviconService::ReplaceFaviconData(nsIURI* aFaviconURI,
const nsACString& aMimeType,
PRTime aExpiration)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aFaviconURI);
NS_ENSURE_ARG(aData);
NS_ENSURE_TRUE(aDataLen > 0, NS_ERROR_INVALID_ARG);
@ -311,8 +351,10 @@ nsFaviconService::ReplaceFaviconData(nsIURI* aFaviconURI,
// If the database contains an icon at the given url, we will update the
// database immediately so that the associated pages are kept in sync.
// Otherwise, do nothing and let the icon be picked up from the memory hash.
rv = AsyncReplaceFaviconData::start(iconData);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<AsyncReplaceFaviconData> event = new AsyncReplaceFaviconData(*iconData);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
return NS_OK;
}
@ -403,11 +445,21 @@ NS_IMETHODIMP
nsFaviconService::GetFaviconURLForPage(nsIURI *aPageURI,
nsIFaviconDataCallback* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aPageURI);
NS_ENSURE_ARG(aCallback);
nsresult rv = AsyncGetFaviconURLForPage::start(aPageURI, aCallback);
nsAutoCString pageSpec;
nsresult rv = aPageURI->GetSpec(pageSpec);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<AsyncGetFaviconURLForPage> event =
new AsyncGetFaviconURLForPage(pageSpec, aCallback);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
return NS_OK;
}
@ -415,11 +467,20 @@ NS_IMETHODIMP
nsFaviconService::GetFaviconDataForPage(nsIURI* aPageURI,
nsIFaviconDataCallback* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aPageURI);
NS_ENSURE_ARG(aCallback);
nsresult rv = AsyncGetFaviconDataForPage::start(aPageURI, aCallback);
nsAutoCString pageSpec;
nsresult rv = aPageURI->GetSpec(pageSpec);
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<AsyncGetFaviconDataForPage> event =
new AsyncGetFaviconDataForPage(pageSpec, aCallback);
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
DB->DispatchToAsyncThread(event);
return NS_OK;
}

Просмотреть файл

@ -21,7 +21,7 @@
#include "mozilla/storage.h"
#include "mozilla/Attributes.h"
#include "AsyncFaviconHelpers.h"
#include "FaviconHelpers.h"
// Favicons bigger than this size should not be saved to the db to avoid
// bloating it with large image blobs.
@ -149,9 +149,8 @@ private:
uint32_t mFailedFaviconSerial;
nsDataHashtable<nsCStringHashKey, uint32_t> mFailedFavicons;
// AsyncFetchAndSetIconForPage needs access to the icon cache
friend class mozilla::places::AsyncFetchAndSetIconForPage;
friend class mozilla::places::RemoveIconDataCacheEntry;
// This class needs access to the icons cache.
friend class mozilla::places::AsyncReplaceFaviconData;
nsTHashtable<UnassociatedIconHashKey> mUnassociatedIcons;
};