mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 722861 - Add privacy information to image requests, and use a separate cache for private requests. r=joe
This commit is contained in:
parent
6eef761549
commit
1c909a96b0
@ -482,13 +482,6 @@ public:
|
||||
return sIOService;
|
||||
}
|
||||
|
||||
static imgILoader* GetImgLoader()
|
||||
{
|
||||
if (!sImgLoaderInitialized)
|
||||
InitImgLoader();
|
||||
return sImgLoader;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XTF
|
||||
static nsIXTFService* GetXTFService();
|
||||
#endif
|
||||
@ -663,10 +656,17 @@ public:
|
||||
int32_t aLoadFlags,
|
||||
imgIRequest** aRequest);
|
||||
|
||||
/**
|
||||
* Obtain an image loader that respects the given document/channel's privacy status.
|
||||
* Null document/channel arguments return the public image loader.
|
||||
*/
|
||||
static imgILoader* GetImgLoaderForDocument(nsIDocument* aDoc);
|
||||
static imgILoader* GetImgLoaderForChannel(nsIChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Returns whether the given URI is in the image cache.
|
||||
*/
|
||||
static bool IsImageInCache(nsIURI* aURI);
|
||||
static bool IsImageInCache(nsIURI* aURI, nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Method to get an imgIContainer from an image loading content
|
||||
@ -2160,9 +2160,11 @@ private:
|
||||
static bool sImgLoaderInitialized;
|
||||
static void InitImgLoader();
|
||||
|
||||
// The following two members are initialized lazily
|
||||
// The following four members are initialized lazily
|
||||
static imgILoader* sImgLoader;
|
||||
static imgILoader* sPrivateImgLoader;
|
||||
static imgICache* sImgCache;
|
||||
static imgICache* sPrivateImgCache;
|
||||
|
||||
static nsIConsoleService* sConsoleService;
|
||||
|
||||
|
@ -50,6 +50,7 @@ EXPORTS_mozilla/dom = \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/image/src \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -119,6 +119,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsParserConstants.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "mozilla/Selection.h"
|
||||
|
||||
@ -134,6 +135,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "imgICache.h"
|
||||
#include "imgLoader.h"
|
||||
#include "xpcprivate.h" // nsXPConnect
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsIChannelPolicy.h"
|
||||
@ -187,7 +189,9 @@ nsIIOService *nsContentUtils::sIOService;
|
||||
nsIXTFService *nsContentUtils::sXTFService = nullptr;
|
||||
#endif
|
||||
imgILoader *nsContentUtils::sImgLoader;
|
||||
imgILoader *nsContentUtils::sPrivateImgLoader;
|
||||
imgICache *nsContentUtils::sImgCache;
|
||||
imgICache *nsContentUtils::sPrivateImgCache;
|
||||
nsIConsoleService *nsContentUtils::sConsoleService;
|
||||
nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nullptr;
|
||||
nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nullptr;
|
||||
@ -508,15 +512,17 @@ nsContentUtils::InitImgLoader()
|
||||
sImgLoaderInitialized = true;
|
||||
|
||||
// Ignore failure and just don't load images
|
||||
nsresult rv = CallGetService("@mozilla.org/image/loader;1", &sImgLoader);
|
||||
if (NS_FAILED(rv)) {
|
||||
// no image loading for us. Oh, well.
|
||||
sImgLoader = nullptr;
|
||||
sImgCache = nullptr;
|
||||
} else {
|
||||
if (NS_FAILED(CallGetService("@mozilla.org/image/cache;1", &sImgCache )))
|
||||
sImgCache = nullptr;
|
||||
}
|
||||
nsresult rv = CallCreateInstance("@mozilla.org/image/loader;1", &sImgLoader);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Creation should have succeeded");
|
||||
rv = CallCreateInstance("@mozilla.org/image/loader;1", &sPrivateImgLoader);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Creation should have succeeded");
|
||||
|
||||
rv = CallQueryInterface(sImgLoader, &sImgCache);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "imgICache and imgILoader should be paired");
|
||||
rv = CallQueryInterface(sPrivateImgLoader, &sPrivateImgCache);
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "imgICache and imgILoader should be paired");
|
||||
|
||||
sPrivateImgCache->RespectPrivacyNotifications();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1493,7 +1499,9 @@ nsContentUtils::Shutdown()
|
||||
NS_IF_RELEASE(sXTFService);
|
||||
#endif
|
||||
NS_IF_RELEASE(sImgLoader);
|
||||
NS_IF_RELEASE(sPrivateImgLoader);
|
||||
NS_IF_RELEASE(sImgCache);
|
||||
NS_IF_RELEASE(sPrivateImgCache);
|
||||
#ifdef IBMBIDI
|
||||
NS_IF_RELEASE(sBidiKeyboard);
|
||||
#endif
|
||||
@ -2692,19 +2700,60 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
|
||||
return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision);
|
||||
}
|
||||
|
||||
imgILoader*
|
||||
nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc)
|
||||
{
|
||||
if (!sImgLoaderInitialized)
|
||||
InitImgLoader();
|
||||
if (!aDoc)
|
||||
return sImgLoader;
|
||||
bool isPrivate = false;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
|
||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||
if (loadGroup) {
|
||||
loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||
if (callbacks) {
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
|
||||
isPrivate = loadContext && loadContext->UsePrivateBrowsing();
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
|
||||
if (channel) {
|
||||
nsCOMPtr<nsILoadContext> context;
|
||||
NS_QueryNotificationCallbacks(channel, context);
|
||||
isPrivate = context && context->UsePrivateBrowsing();
|
||||
}
|
||||
}
|
||||
return isPrivate ? sPrivateImgLoader : sImgLoader;
|
||||
}
|
||||
|
||||
// static
|
||||
imgILoader*
|
||||
nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel)
|
||||
{
|
||||
if (!sImgLoaderInitialized)
|
||||
InitImgLoader();
|
||||
if (!aChannel)
|
||||
return sImgLoader;
|
||||
nsCOMPtr<nsILoadContext> context;
|
||||
NS_QueryNotificationCallbacks(aChannel, context);
|
||||
return context && context->UsePrivateBrowsing() ? sPrivateImgLoader : sImgLoader;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::IsImageInCache(nsIURI* aURI)
|
||||
nsContentUtils::IsImageInCache(nsIURI* aURI, nsIDocument* aDocument)
|
||||
{
|
||||
if (!sImgLoaderInitialized)
|
||||
InitImgLoader();
|
||||
|
||||
if (!sImgCache) return false;
|
||||
imgILoader* loader = GetImgLoaderForDocument(aDocument);
|
||||
nsCOMPtr<imgICache> cache = do_QueryInterface(loader);
|
||||
|
||||
// If something unexpected happened we return false, otherwise if props
|
||||
// is set, the image is cached and we return true
|
||||
nsCOMPtr<nsIProperties> props;
|
||||
nsresult rv = sImgCache->FindEntryProperties(aURI, getter_AddRefs(props));
|
||||
nsresult rv = cache->FindEntryProperties(aURI, getter_AddRefs(props));
|
||||
return (NS_SUCCEEDED(rv) && props);
|
||||
}
|
||||
|
||||
@ -2720,7 +2769,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
|
||||
NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
|
||||
NS_PRECONDITION(aRequest, "Null out param");
|
||||
|
||||
imgILoader* imgLoader = GetImgLoader();
|
||||
imgILoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
|
||||
if (!imgLoader) {
|
||||
// nothing we can do here
|
||||
return NS_OK;
|
||||
|
@ -7681,7 +7681,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr)
|
||||
// which indicates that the "real" load has already started and
|
||||
// that we shouldn't preload it.
|
||||
int16_t blockingStatus;
|
||||
if (nsContentUtils::IsImageInCache(uri) ||
|
||||
if (nsContentUtils::IsImageInCache(uri, static_cast<nsIDocument *>(this)) ||
|
||||
!nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
|
||||
this, NodePrincipal(), &blockingStatus)) {
|
||||
return;
|
||||
|
@ -88,7 +88,7 @@ nsImageLoadingContent::nsImageLoadingContent()
|
||||
mCurrentRequestRegistered(false),
|
||||
mPendingRequestRegistered(false)
|
||||
{
|
||||
if (!nsContentUtils::GetImgLoader()) {
|
||||
if (!nsContentUtils::GetImgLoaderForChannel(nullptr)) {
|
||||
mLoadingEnabled = false;
|
||||
}
|
||||
}
|
||||
@ -334,7 +334,7 @@ nsImageLoadingContent::SetLoadingEnabled(bool aLoadingEnabled)
|
||||
{
|
||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (nsContentUtils::GetImgLoader()) {
|
||||
if (nsContentUtils::GetImgLoaderForChannel(nullptr)) {
|
||||
mLoadingEnabled = aLoadingEnabled;
|
||||
}
|
||||
return NS_OK;
|
||||
@ -518,7 +518,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
|
||||
{
|
||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
if (!nsContentUtils::GetImgLoader()) {
|
||||
if (!nsContentUtils::GetImgLoaderForChannel(aChannel)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
@ -537,7 +537,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
|
||||
|
||||
// Do the load.
|
||||
nsCOMPtr<imgIRequest>& req = PrepareNextRequest();
|
||||
nsresult rv = nsContentUtils::GetImgLoader()->
|
||||
nsresult rv = nsContentUtils::GetImgLoaderForChannel(aChannel)->
|
||||
LoadImageWithChannel(aChannel, this, doc, aListener,
|
||||
getter_AddRefs(req));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
@ -477,7 +477,7 @@ URIEquals(nsIURI *a, nsIURI *b)
|
||||
static bool
|
||||
IsSupportedImage(const nsCString& aMimeType)
|
||||
{
|
||||
imgILoader* loader = nsContentUtils::GetImgLoader();
|
||||
nsCOMPtr<imgILoader> loader = nsContentUtils::GetImgLoaderForChannel(nullptr);
|
||||
if (!loader) {
|
||||
return false;
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ nsWebNavigationInfo::Init()
|
||||
mCategoryManager = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mImgLoader = do_GetService("@mozilla.org/image/loader;1", &rv);
|
||||
mImgLoader = nsContentUtils::GetImgLoaderForChannel(nullptr);
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -301,8 +301,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR
|
||||
NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
|
||||
NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<imgILoader> il(do_GetService(
|
||||
"@mozilla.org/image/loader;1"));
|
||||
nsCOMPtr<imgILoader> il(do_CreateInstance("@mozilla.org/image/loader;1"));
|
||||
NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
|
||||
|
||||
return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr,
|
||||
|
@ -96,7 +96,7 @@ static nsresult
|
||||
imglib_Initialize()
|
||||
{
|
||||
mozilla::image::DiscardTracker::Initialize();
|
||||
imgLoader::InitCache();
|
||||
imgLoader::GlobalInit();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ interface nsIProperties;
|
||||
* @version 0.1
|
||||
* @see imagelib2
|
||||
*/
|
||||
[scriptable, uuid(f1b74aae-5661-4753-a21c-66dd644afebc)]
|
||||
[scriptable, uuid(b06e0fa5-d6e2-4fa3-8fc0-7775aed96522)]
|
||||
interface imgICache : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -49,4 +49,11 @@ interface imgICache : nsISupports
|
||||
* @returns NULL if the URL was not found in the cache
|
||||
*/
|
||||
nsIProperties findEntryProperties(in nsIURI uri);
|
||||
|
||||
/**
|
||||
* Make this cache instance respect private browsing notifications. This entails clearing
|
||||
* the chrome and content caches whenever the last-pb-context-exited notification is
|
||||
* observed.
|
||||
*/
|
||||
void respectPrivacyNotifications();
|
||||
};
|
||||
|
@ -8,8 +8,11 @@
|
||||
|
||||
interface nsIInputStream;
|
||||
interface imgIContainer;
|
||||
interface imgILoader;
|
||||
interface imgICache;
|
||||
interface nsIDOMDocument;
|
||||
|
||||
[scriptable, uuid(8e16f39e-7012-46bd-aa22-2a7a3265608f)]
|
||||
[scriptable, uuid(53dd1cbe-cb9f-4d9e-8104-1ab72851c88e)]
|
||||
interface imgITools : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -71,6 +74,26 @@ interface imgITools : nsISupports
|
||||
in long aHeight,
|
||||
[optional] in AString outputOptions);
|
||||
|
||||
/**
|
||||
* getImgLoaderForDocument
|
||||
* Retrieve an image loader that reflects the privacy status of the given
|
||||
* document.
|
||||
*
|
||||
* @param doc
|
||||
* A document. Must not be null.
|
||||
*/
|
||||
imgILoader getImgLoaderForDocument(in nsIDOMDocument doc);
|
||||
|
||||
/**
|
||||
* getImgLoaderForDocument
|
||||
* Retrieve an image cache that reflects the privacy status of the given
|
||||
* document.
|
||||
*
|
||||
* @param doc
|
||||
* A document. Must not be null.
|
||||
*/
|
||||
imgICache getImgCacheForDocument(in nsIDOMDocument doc);
|
||||
|
||||
/**
|
||||
* encodeCroppedImage
|
||||
* Caller provides an image container, and the mime type it should be
|
||||
|
@ -50,7 +50,6 @@
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
|
||||
// we want to explore making the document own the load group
|
||||
// so we can associate the document URI with the load group.
|
||||
@ -58,6 +57,7 @@
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIChannelPolicy.h"
|
||||
#include "nsILoadContext.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
@ -87,8 +87,11 @@ public:
|
||||
{
|
||||
AllSizes chrome;
|
||||
AllSizes content;
|
||||
imgLoader::sChromeCache.EnumerateRead(EntryAllSizes, &chrome);
|
||||
imgLoader::sCache.EnumerateRead(EntryAllSizes, &content);
|
||||
|
||||
for (PRUint32 i = 0; i < mKnownLoaders.Length(); i++) {
|
||||
mKnownLoaders[i]->mChromeCache.EnumerateRead(EntryAllSizes, &chrome);
|
||||
mKnownLoaders[i]->mCache.EnumerateRead(EntryAllSizes, &content);
|
||||
}
|
||||
|
||||
#define REPORT(_path, _kind, _amount, _desc) \
|
||||
do { \
|
||||
@ -155,8 +158,10 @@ public:
|
||||
NS_IMETHOD GetExplicitNonHeap(int64_t *n)
|
||||
{
|
||||
size_t n2 = 0;
|
||||
imgLoader::sChromeCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
|
||||
imgLoader::sCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
|
||||
for (PRUint32 i = 0; i < mKnownLoaders.Length(); i++) {
|
||||
mKnownLoaders[i]->mChromeCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
|
||||
mKnownLoaders[i]->mCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
|
||||
}
|
||||
*n = n2;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -164,11 +169,25 @@ public:
|
||||
static int64_t GetImagesContentUsedUncompressed()
|
||||
{
|
||||
size_t n = 0;
|
||||
imgLoader::sCache.EnumerateRead(EntryUsedUncompressedSize, &n);
|
||||
for (PRUint32 i = 0; i < imgLoader::sMemReporter->mKnownLoaders.Length(); i++) {
|
||||
imgLoader::sMemReporter->mKnownLoaders[i]->mCache.EnumerateRead(EntryUsedUncompressedSize, &n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void RegisterLoader(imgLoader* aLoader)
|
||||
{
|
||||
mKnownLoaders.AppendElement(aLoader);
|
||||
}
|
||||
|
||||
void UnregisterLoader(imgLoader* aLoader)
|
||||
{
|
||||
mKnownLoaders.RemoveElement(aLoader);
|
||||
}
|
||||
|
||||
private:
|
||||
nsTArray<imgLoader*> mKnownLoaders;
|
||||
|
||||
struct AllSizes {
|
||||
size_t mUsedRaw;
|
||||
size_t mUsedUncompressedHeap;
|
||||
@ -339,11 +358,11 @@ nsProgressNotificationProxy::GetInterface(const nsIID& iid,
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
static void NewRequestAndEntry(bool aForcePrincipalCheckForCacheEntry,
|
||||
static void NewRequestAndEntry(bool aForcePrincipalCheckForCacheEntry, imgLoader* aLoader,
|
||||
imgRequest **aRequest, imgCacheEntry **aEntry)
|
||||
{
|
||||
nsRefPtr<imgRequest> request = new imgRequest();
|
||||
nsRefPtr<imgCacheEntry> entry = new imgCacheEntry(request, aForcePrincipalCheckForCacheEntry);
|
||||
nsRefPtr<imgRequest> request = new imgRequest(aLoader);
|
||||
nsRefPtr<imgCacheEntry> entry = new imgCacheEntry(aLoader, request, aForcePrincipalCheckForCacheEntry);
|
||||
request.forget(aRequest);
|
||||
entry.forget(aEntry);
|
||||
}
|
||||
@ -511,8 +530,9 @@ static uint32_t SecondsFromPRTime(PRTime prTime)
|
||||
return uint32_t(int64_t(prTime) / int64_t(PR_USEC_PER_SEC));
|
||||
}
|
||||
|
||||
imgCacheEntry::imgCacheEntry(imgRequest *request, bool forcePrincipalCheck)
|
||||
: mRequest(request),
|
||||
imgCacheEntry::imgCacheEntry(imgLoader* loader, imgRequest *request, bool forcePrincipalCheck)
|
||||
: mLoader(loader),
|
||||
mRequest(request),
|
||||
mDataSize(0),
|
||||
mTouchedTime(SecondsFromPRTime(PR_Now())),
|
||||
mExpiryTime(0),
|
||||
@ -546,7 +566,7 @@ void imgCacheEntry::UpdateCache(int32_t diff /* = 0 */)
|
||||
if (!Evicted() && HasNoProxies()) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mRequest->GetURI(getter_AddRefs(uri));
|
||||
imgLoader::CacheEntriesChanged(uri, diff);
|
||||
mLoader->CacheEntriesChanged(uri, diff);
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,8 +726,6 @@ class imgCacheObserver MOZ_FINAL : public nsIObserver
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
private:
|
||||
imgLoader mLoader;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(imgCacheObserver, nsIObserver)
|
||||
@ -717,10 +735,6 @@ imgCacheObserver::Observe(nsISupports* aSubject, const char* aTopic, const PRUni
|
||||
{
|
||||
if (strcmp(aTopic, "memory-pressure") == 0) {
|
||||
DiscardTracker::DiscardAll();
|
||||
mLoader.MinimizeCaches();
|
||||
} else if (strcmp(aTopic, "chrome-flush-skin-caches") == 0 ||
|
||||
strcmp(aTopic, "chrome-flush-caches") == 0) {
|
||||
mLoader.ClearChromeImageCache();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -760,45 +774,44 @@ void imgCacheExpirationTracker::NotifyExpired(imgCacheEntry *entry)
|
||||
// We can be called multiple times on the same entry. Don't do work multiple
|
||||
// times.
|
||||
if (!entry->Evicted())
|
||||
imgLoader::RemoveFromCache(entry);
|
||||
entry->Loader()->RemoveFromCache(entry);
|
||||
|
||||
imgLoader::VerifyCacheSizes();
|
||||
entry->Loader()->VerifyCacheSizes();
|
||||
}
|
||||
|
||||
imgCacheObserver *gCacheObserver;
|
||||
imgCacheExpirationTracker *gCacheTracker;
|
||||
|
||||
imgLoader::imgCacheTable imgLoader::sCache;
|
||||
imgCacheQueue imgLoader::sCacheQueue;
|
||||
|
||||
imgLoader::imgCacheTable imgLoader::sChromeCache;
|
||||
imgCacheQueue imgLoader::sChromeCacheQueue;
|
||||
|
||||
double imgLoader::sCacheTimeWeight;
|
||||
uint32_t imgLoader::sCacheMaxSize;
|
||||
imgMemoryReporter* imgLoader::sMemReporter;
|
||||
|
||||
NS_IMPL_ISUPPORTS5(imgLoader, imgILoader, nsIContentSniffer, imgICache, nsISupportsWeakReference, nsIObserver)
|
||||
|
||||
imgLoader::imgLoader()
|
||||
: mRespectPrivacy(false)
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
sMemReporter->AddRef();
|
||||
sMemReporter->RegisterLoader(this);
|
||||
}
|
||||
|
||||
imgLoader::~imgLoader()
|
||||
{
|
||||
/* destructor code */
|
||||
ClearChromeImageCache();
|
||||
ClearImageCache();
|
||||
sMemReporter->UnregisterLoader(this);
|
||||
sMemReporter->Release();
|
||||
}
|
||||
|
||||
void imgLoader::VerifyCacheSizes()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!gCacheTracker)
|
||||
if (!mCacheTracker)
|
||||
return;
|
||||
|
||||
uint32_t cachesize = sCache.Count() + sChromeCache.Count();
|
||||
uint32_t queuesize = sCacheQueue.GetNumElements() + sChromeCacheQueue.GetNumElements();
|
||||
uint32_t cachesize = mCache.Count() + mChromeCache.Count();
|
||||
uint32_t queuesize = mCacheQueue.GetNumElements() + mChromeCacheQueue.GetNumElements();
|
||||
uint32_t trackersize = 0;
|
||||
for (nsExpirationTracker<imgCacheEntry, 3>::Iterator it(gCacheTracker); it.Next(); )
|
||||
for (nsExpirationTracker<imgCacheEntry, 3>::Iterator it(mCacheTracker); it.Next(); )
|
||||
trackersize++;
|
||||
NS_ABORT_IF_FALSE(queuesize == trackersize, "Queue and tracker sizes out of sync!");
|
||||
NS_ABORT_IF_FALSE(queuesize <= cachesize, "Queue has more elements than cache!");
|
||||
@ -810,9 +823,9 @@ imgLoader::imgCacheTable & imgLoader::GetCache(nsIURI *aURI)
|
||||
bool chrome = false;
|
||||
aURI->SchemeIs("chrome", &chrome);
|
||||
if (chrome)
|
||||
return sChromeCache;
|
||||
return mChromeCache;
|
||||
else
|
||||
return sCache;
|
||||
return mCache;
|
||||
}
|
||||
|
||||
imgCacheQueue & imgLoader::GetCacheQueue(nsIURI *aURI)
|
||||
@ -820,34 +833,22 @@ imgCacheQueue & imgLoader::GetCacheQueue(nsIURI *aURI)
|
||||
bool chrome = false;
|
||||
aURI->SchemeIs("chrome", &chrome);
|
||||
if (chrome)
|
||||
return sChromeCacheQueue;
|
||||
return mChromeCacheQueue;
|
||||
else
|
||||
return sCacheQueue;
|
||||
return mCacheQueue;
|
||||
}
|
||||
|
||||
nsresult imgLoader::InitCache()
|
||||
void imgLoader::GlobalInit()
|
||||
{
|
||||
NS_TIME_FUNCTION;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (!os)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gCacheObserver = new imgCacheObserver();
|
||||
NS_ADDREF(gCacheObserver);
|
||||
|
||||
os->AddObserver(gCacheObserver, "memory-pressure", false);
|
||||
os->AddObserver(gCacheObserver, "chrome-flush-skin-caches", false);
|
||||
os->AddObserver(gCacheObserver, "chrome-flush-caches", false);
|
||||
|
||||
gCacheTracker = new imgCacheExpirationTracker();
|
||||
|
||||
sCache.Init();
|
||||
sChromeCache.Init();
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (os)
|
||||
os->AddObserver(gCacheObserver, "memory-pressure", false);
|
||||
|
||||
int32_t timeweight;
|
||||
rv = Preferences::GetInt("image.cache.timeweight", &timeweight);
|
||||
nsresult rv = Preferences::GetInt("image.cache.timeweight", &timeweight);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
sCacheTimeWeight = timeweight / 1000.0;
|
||||
else
|
||||
@ -860,23 +861,49 @@ nsresult imgLoader::InitCache()
|
||||
else
|
||||
sCacheMaxSize = 5 * 1024 * 1024;
|
||||
|
||||
NS_RegisterMemoryMultiReporter(new imgMemoryReporter());
|
||||
sMemReporter = new imgMemoryReporter();
|
||||
NS_RegisterMemoryMultiReporter(sMemReporter);
|
||||
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ImagesContentUsedUncompressed));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult imgLoader::InitCache()
|
||||
{
|
||||
NS_TIME_FUNCTION;
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (!os)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
os->AddObserver(this, "memory-pressure", false);
|
||||
os->AddObserver(this, "chrome-flush-skin-caches", false);
|
||||
os->AddObserver(this, "chrome-flush-caches", false);
|
||||
os->AddObserver(this, "last-pb-context-exited", false);
|
||||
os->AddObserver(this, "profile-before-change", false);
|
||||
os->AddObserver(this, "xpcom-shutdown", false);
|
||||
|
||||
mCacheTracker = new imgCacheExpirationTracker();
|
||||
|
||||
mCache.Init();
|
||||
mChromeCache.Init();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult imgLoader::Init()
|
||||
{
|
||||
InitCache();
|
||||
|
||||
ReadAcceptHeaderPref();
|
||||
|
||||
Preferences::AddWeakObserver(this, "image.http.accept");
|
||||
|
||||
// Listen for when we leave private browsing mode
|
||||
nsCOMPtr<nsIObserverService> obService = mozilla::services::GetObserverService();
|
||||
if (obService)
|
||||
obService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgLoader::RespectPrivacyNotifications()
|
||||
{
|
||||
mRespectPrivacy = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -888,12 +915,21 @@ imgLoader::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* a
|
||||
if (!strcmp(NS_ConvertUTF16toUTF8(aData).get(), "image.http.accept")) {
|
||||
ReadAcceptHeaderPref();
|
||||
}
|
||||
}
|
||||
|
||||
// ...and exits from private browsing.
|
||||
else if (!strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC)) {
|
||||
if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData))
|
||||
} else if (strcmp(aTopic, "memory-pressure") == 0) {
|
||||
MinimizeCaches();
|
||||
} else if (strcmp(aTopic, "chrome-flush-skin-caches") == 0 ||
|
||||
strcmp(aTopic, "chrome-flush-caches") == 0) {
|
||||
MinimizeCaches();
|
||||
ClearChromeImageCache();
|
||||
} else if (strcmp(aTopic, "last-pb-context-exited") == 0) {
|
||||
if (mRespectPrivacy) {
|
||||
ClearImageCache();
|
||||
ClearChromeImageCache();
|
||||
}
|
||||
} else if (strcmp(aTopic, "profile-before-change") == 0 ||
|
||||
strcmp(aTopic, "xpcom-shutdown") == 0) {
|
||||
mCacheTracker = nullptr;
|
||||
}
|
||||
|
||||
// (Nothing else should bring us here)
|
||||
@ -942,8 +978,8 @@ NS_IMETHODIMP imgLoader::FindEntryProperties(nsIURI *uri, nsIProperties **_retva
|
||||
*_retval = nullptr;
|
||||
|
||||
if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
|
||||
if (gCacheTracker && entry->HasNoProxies())
|
||||
gCacheTracker->MarkUsed(entry);
|
||||
if (mCacheTracker && entry->HasNoProxies())
|
||||
mCacheTracker->MarkUsed(entry);
|
||||
|
||||
nsRefPtr<imgRequest> request = getter_AddRefs(entry->GetRequest());
|
||||
if (request) {
|
||||
@ -957,27 +993,23 @@ NS_IMETHODIMP imgLoader::FindEntryProperties(nsIURI *uri, nsIProperties **_retva
|
||||
|
||||
void imgLoader::Shutdown()
|
||||
{
|
||||
ClearChromeImageCache();
|
||||
ClearImageCache();
|
||||
NS_IF_RELEASE(gCacheObserver);
|
||||
delete gCacheTracker;
|
||||
gCacheTracker = nullptr;
|
||||
NS_RELEASE(gCacheObserver);
|
||||
}
|
||||
|
||||
nsresult imgLoader::ClearChromeImageCache()
|
||||
{
|
||||
return EvictEntries(sChromeCache);
|
||||
return EvictEntries(mChromeCache);
|
||||
}
|
||||
|
||||
nsresult imgLoader::ClearImageCache()
|
||||
{
|
||||
return EvictEntries(sCache);
|
||||
return EvictEntries(mCache);
|
||||
}
|
||||
|
||||
void imgLoader::MinimizeCaches()
|
||||
{
|
||||
EvictEntries(sCacheQueue);
|
||||
EvictEntries(sChromeCacheQueue);
|
||||
EvictEntries(mCacheQueue);
|
||||
EvictEntries(mChromeCacheQueue);
|
||||
}
|
||||
|
||||
bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
|
||||
@ -1020,8 +1052,8 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
|
||||
if (entry->HasNoProxies()) {
|
||||
nsresult addrv = NS_OK;
|
||||
|
||||
if (gCacheTracker)
|
||||
addrv = gCacheTracker->AddObject(entry);
|
||||
if (mCacheTracker)
|
||||
addrv = mCacheTracker->AddObject(entry);
|
||||
|
||||
if (NS_SUCCEEDED(addrv)) {
|
||||
imgCacheQueue &queue = GetCacheQueue(key);
|
||||
@ -1051,8 +1083,8 @@ bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
|
||||
|
||||
nsresult addrv = NS_OK;
|
||||
|
||||
if (gCacheTracker)
|
||||
addrv = gCacheTracker->AddObject(entry);
|
||||
if (mCacheTracker)
|
||||
addrv = mCacheTracker->AddObject(entry);
|
||||
|
||||
if (NS_SUCCEEDED(addrv)) {
|
||||
queue.Push(entry);
|
||||
@ -1081,8 +1113,8 @@ bool imgLoader::SetHasProxies(nsIURI *key)
|
||||
imgCacheQueue &queue = GetCacheQueue(key);
|
||||
queue.Remove(entry);
|
||||
|
||||
if (gCacheTracker)
|
||||
gCacheTracker->RemoveObject(entry);
|
||||
if (mCacheTracker)
|
||||
mCacheTracker->RemoveObject(entry);
|
||||
|
||||
entry->SetHasNoProxies(false);
|
||||
|
||||
@ -1207,7 +1239,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
|
||||
return false;
|
||||
|
||||
nsRefPtr<imgCacheValidator> hvc =
|
||||
new imgCacheValidator(progressproxy, request, aCX, forcePrincipalCheck);
|
||||
new imgCacheValidator(progressproxy, this, request, aCX, forcePrincipalCheck);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener = hvc.get();
|
||||
|
||||
@ -1388,8 +1420,8 @@ bool imgLoader::RemoveFromCache(nsIURI *aKey)
|
||||
|
||||
// Entries with no proxies are in the tracker.
|
||||
if (entry->HasNoProxies()) {
|
||||
if (gCacheTracker)
|
||||
gCacheTracker->RemoveObject(entry);
|
||||
if (mCacheTracker)
|
||||
mCacheTracker->RemoveObject(entry);
|
||||
queue.Remove(entry);
|
||||
}
|
||||
|
||||
@ -1423,8 +1455,8 @@ bool imgLoader::RemoveFromCache(imgCacheEntry *entry)
|
||||
|
||||
if (entry->HasNoProxies()) {
|
||||
LOG_STATIC_FUNC(gImgLog, "imgLoader::RemoveFromCache removing from tracker");
|
||||
if (gCacheTracker)
|
||||
gCacheTracker->RemoveObject(entry);
|
||||
if (mCacheTracker)
|
||||
mCacheTracker->RemoveObject(entry);
|
||||
queue.Remove(entry);
|
||||
}
|
||||
|
||||
@ -1524,6 +1556,25 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
|
||||
nsresult rv;
|
||||
nsLoadFlags requestFlags = nsIRequest::LOAD_NORMAL;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool isPrivate = false;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (channel) {
|
||||
nsCOMPtr<nsILoadContext> loadContext;
|
||||
NS_QueryNotificationCallbacks(channel, loadContext);
|
||||
isPrivate = loadContext && loadContext->UsePrivateBrowsing();
|
||||
} else if (aLoadGroup) {
|
||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||
if (callbacks) {
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
|
||||
isPrivate = loadContext && loadContext->UsePrivateBrowsing();
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(isPrivate == mRespectPrivacy);
|
||||
#endif
|
||||
|
||||
// Get the default load flags from the loadgroup (if possible)...
|
||||
if (aLoadGroup) {
|
||||
aLoadGroup->GetLoadFlags(&requestFlags);
|
||||
@ -1577,8 +1628,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
|
||||
NS_ABORT_IF_FALSE(!request->HasCacheEntry(), "Proxyless entry's request has cache entry!");
|
||||
request->SetCacheEntry(entry);
|
||||
|
||||
if (gCacheTracker)
|
||||
gCacheTracker->MarkUsed(entry);
|
||||
if (mCacheTracker)
|
||||
mCacheTracker->MarkUsed(entry);
|
||||
}
|
||||
|
||||
entry->Touch();
|
||||
@ -1615,8 +1666,13 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NewRequestAndEntry(forcePrincipalCheck, getter_AddRefs(request),
|
||||
getter_AddRefs(entry));
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsILoadContext> loadContext;
|
||||
NS_QueryNotificationCallbacks(newChannel, loadContext);
|
||||
MOZ_ASSERT_IF(loadContext, loadContext->UsePrivateBrowsing() == mRespectPrivacy);
|
||||
#endif
|
||||
|
||||
NewRequestAndEntry(forcePrincipalCheck, this, getter_AddRefs(request), getter_AddRefs(entry));
|
||||
|
||||
PR_LOG(gImgLog, PR_LOG_DEBUG,
|
||||
("[this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p]\n", this, request.get()));
|
||||
@ -1741,6 +1797,12 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
|
||||
{
|
||||
NS_ASSERTION(channel, "imgLoader::LoadImageWithChannel -- NULL channel pointer");
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsILoadContext> loadContext;
|
||||
NS_QueryNotificationCallbacks(channel, loadContext);
|
||||
MOZ_ASSERT_IF(loadContext, loadContext->UsePrivateBrowsing() == mRespectPrivacy);
|
||||
#endif
|
||||
|
||||
nsRefPtr<imgRequest> request;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
@ -1798,8 +1860,8 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
|
||||
NS_ABORT_IF_FALSE(!request->HasCacheEntry(), "Proxyless entry's request has cache entry!");
|
||||
request->SetCacheEntry(entry);
|
||||
|
||||
if (gCacheTracker)
|
||||
gCacheTracker->MarkUsed(entry);
|
||||
if (mCacheTracker)
|
||||
mCacheTracker->MarkUsed(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1826,7 +1888,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
|
||||
// Default to doing a principal check because we don't know who
|
||||
// started that load and whether their principal ended up being
|
||||
// inherited on the channel.
|
||||
NewRequestAndEntry(true, getter_AddRefs(request), getter_AddRefs(entry));
|
||||
NewRequestAndEntry(true, this, getter_AddRefs(request), getter_AddRefs(entry));
|
||||
|
||||
// We use originalURI here to fulfil the imgIRequest contract on GetURI.
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
@ -2038,17 +2100,16 @@ NS_IMPL_ISUPPORTS5(imgCacheValidator, nsIStreamListener, nsIRequestObserver,
|
||||
nsIChannelEventSink, nsIInterfaceRequestor,
|
||||
nsIAsyncVerifyRedirectCallback)
|
||||
|
||||
imgLoader imgCacheValidator::sImgLoader;
|
||||
|
||||
imgCacheValidator::imgCacheValidator(nsProgressNotificationProxy* progress,
|
||||
imgRequest *request, void *aContext,
|
||||
bool forcePrincipalCheckForCacheEntry)
|
||||
imgLoader* loader, imgRequest *request,
|
||||
void *aContext, bool forcePrincipalCheckForCacheEntry)
|
||||
: mProgressProxy(progress),
|
||||
mRequest(request),
|
||||
mContext(aContext)
|
||||
mContext(aContext),
|
||||
mImgLoader(loader)
|
||||
{
|
||||
NewRequestAndEntry(forcePrincipalCheckForCacheEntry,
|
||||
getter_AddRefs(mNewRequest), getter_AddRefs(mNewEntry));
|
||||
NewRequestAndEntry(forcePrincipalCheckForCacheEntry, loader, getter_AddRefs(mNewRequest),
|
||||
getter_AddRefs(mNewEntry));
|
||||
}
|
||||
|
||||
imgCacheValidator::~imgCacheValidator()
|
||||
@ -2151,7 +2212,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
|
||||
// Try to add the new request into the cache. Note that the entry must be in
|
||||
// the cache before the proxies' ownership changes, because adding a proxy
|
||||
// changes the caching behaviour for imgRequests.
|
||||
sImgLoader.PutIntoCache(originalURI, mNewEntry);
|
||||
mImgLoader->PutIntoCache(originalURI, mNewEntry);
|
||||
|
||||
uint32_t count = mProxies.Count();
|
||||
for (int32_t i = count-1; i>=0; i--) {
|
||||
|
@ -27,16 +27,19 @@
|
||||
#include "prlock.h"
|
||||
#endif
|
||||
|
||||
class imgLoader;
|
||||
class imgRequest;
|
||||
class imgRequestProxy;
|
||||
class imgIRequest;
|
||||
class imgIDecoderObserver;
|
||||
class nsILoadGroup;
|
||||
class imgCacheExpirationTracker;
|
||||
class imgMemoryReporter;
|
||||
|
||||
class imgCacheEntry
|
||||
{
|
||||
public:
|
||||
imgCacheEntry(imgRequest *request, bool aForcePrincipalCheck);
|
||||
imgCacheEntry(imgLoader* loader, imgRequest *request, bool aForcePrincipalCheck);
|
||||
~imgCacheEntry();
|
||||
|
||||
nsrefcnt AddRef()
|
||||
@ -130,6 +133,11 @@ public:
|
||||
return mForcePrincipalCheck;
|
||||
}
|
||||
|
||||
imgLoader* Loader() const
|
||||
{
|
||||
return mLoader;
|
||||
}
|
||||
|
||||
private: // methods
|
||||
friend class imgLoader;
|
||||
friend class imgCacheQueue;
|
||||
@ -148,6 +156,7 @@ private: // data
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
imgLoader* mLoader;
|
||||
nsRefPtr<imgRequest> mRequest;
|
||||
uint32_t mDataSize;
|
||||
int32_t mTouchedTime;
|
||||
@ -219,18 +228,19 @@ public:
|
||||
|
||||
static nsresult GetMimeTypeFromContent(const char* aContents, uint32_t aLength, nsACString& aContentType);
|
||||
|
||||
static void GlobalInit(); // for use by the factory
|
||||
static void Shutdown(); // for use by the factory
|
||||
|
||||
static nsresult ClearChromeImageCache();
|
||||
static nsresult ClearImageCache();
|
||||
static void MinimizeCaches();
|
||||
nsresult ClearChromeImageCache();
|
||||
nsresult ClearImageCache();
|
||||
void MinimizeCaches();
|
||||
|
||||
static nsresult InitCache();
|
||||
nsresult InitCache();
|
||||
|
||||
static bool RemoveFromCache(nsIURI *aKey);
|
||||
static bool RemoveFromCache(imgCacheEntry *entry);
|
||||
bool RemoveFromCache(nsIURI *aKey);
|
||||
bool RemoveFromCache(imgCacheEntry *entry);
|
||||
|
||||
static bool PutIntoCache(nsIURI *key, imgCacheEntry *entry);
|
||||
bool PutIntoCache(nsIURI *key, imgCacheEntry *entry);
|
||||
|
||||
// Returns true if we should prefer evicting cache entry |two| over cache
|
||||
// entry |one|.
|
||||
@ -256,7 +266,7 @@ public:
|
||||
return oneweight < twoweight;
|
||||
}
|
||||
|
||||
static void VerifyCacheSizes();
|
||||
void VerifyCacheSizes();
|
||||
|
||||
// The image loader maintains a hash table of all imgCacheEntries. However,
|
||||
// only some of them will be evicted from the cache: those who have no
|
||||
@ -269,8 +279,8 @@ public:
|
||||
// HasObservers(). The request's cache entry will be re-set before this
|
||||
// happens, by calling imgRequest::SetCacheEntry() when an entry with no
|
||||
// observers is re-requested.
|
||||
static bool SetHasNoProxies(nsIURI *key, imgCacheEntry *entry);
|
||||
static bool SetHasProxies(nsIURI *key);
|
||||
bool SetHasNoProxies(nsIURI *key, imgCacheEntry *entry);
|
||||
bool SetHasProxies(nsIURI *key);
|
||||
|
||||
private: // methods
|
||||
|
||||
@ -307,27 +317,32 @@ private: // methods
|
||||
|
||||
typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
|
||||
|
||||
static nsresult EvictEntries(imgCacheTable &aCacheToClear);
|
||||
static nsresult EvictEntries(imgCacheQueue &aQueueToClear);
|
||||
nsresult EvictEntries(imgCacheTable &aCacheToClear);
|
||||
nsresult EvictEntries(imgCacheQueue &aQueueToClear);
|
||||
|
||||
static imgCacheTable &GetCache(nsIURI *aURI);
|
||||
static imgCacheQueue &GetCacheQueue(nsIURI *aURI);
|
||||
static void CacheEntriesChanged(nsIURI *aURI, int32_t sizediff = 0);
|
||||
static void CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue);
|
||||
imgCacheTable &GetCache(nsIURI *aURI);
|
||||
imgCacheQueue &GetCacheQueue(nsIURI *aURI);
|
||||
void CacheEntriesChanged(nsIURI *aURI, PRInt32 sizediff = 0);
|
||||
void CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue);
|
||||
|
||||
private: // data
|
||||
friend class imgCacheEntry;
|
||||
friend class imgMemoryReporter;
|
||||
|
||||
static imgCacheTable sCache;
|
||||
static imgCacheQueue sCacheQueue;
|
||||
imgCacheTable mCache;
|
||||
imgCacheQueue mCacheQueue;
|
||||
|
||||
imgCacheTable mChromeCache;
|
||||
imgCacheQueue mChromeCacheQueue;
|
||||
|
||||
static imgCacheTable sChromeCache;
|
||||
static imgCacheQueue sChromeCacheQueue;
|
||||
static double sCacheTimeWeight;
|
||||
static uint32_t sCacheMaxSize;
|
||||
static imgMemoryReporter* sMemReporter;
|
||||
|
||||
nsCString mAcceptHeader;
|
||||
|
||||
nsAutoPtr<imgCacheExpirationTracker> mCacheTracker;
|
||||
bool mRespectPrivacy;
|
||||
};
|
||||
|
||||
|
||||
@ -395,8 +410,8 @@ class imgCacheValidator : public nsIStreamListener,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
{
|
||||
public:
|
||||
imgCacheValidator(nsProgressNotificationProxy* progress, imgRequest *request,
|
||||
void *aContext, bool forcePrincipalCheckForCacheEntry);
|
||||
imgCacheValidator(nsProgressNotificationProxy* progress, imgLoader* loader,
|
||||
imgRequest *request, void *aContext, bool forcePrincipalCheckForCacheEntry);
|
||||
virtual ~imgCacheValidator();
|
||||
|
||||
void AddProxy(imgRequestProxy *aProxy);
|
||||
@ -422,7 +437,7 @@ private:
|
||||
|
||||
void *mContext;
|
||||
|
||||
static imgLoader sImgLoader;
|
||||
imgLoader* mImgLoader;
|
||||
};
|
||||
|
||||
#endif // imgLoader_h__
|
||||
|
@ -79,8 +79,8 @@ NS_IMPL_ISUPPORTS8(imgRequest,
|
||||
nsIInterfaceRequestor,
|
||||
nsIAsyncVerifyRedirectCallback)
|
||||
|
||||
imgRequest::imgRequest() :
|
||||
mValidator(nullptr), mImageSniffers("image-sniffing-services"),
|
||||
imgRequest::imgRequest(imgLoader* aLoader) :
|
||||
mLoader(aLoader), mValidator(nullptr), mImageSniffers("image-sniffing-services"),
|
||||
mInnerWindowId(0), mCORSMode(imgIRequest::CORS_NONE),
|
||||
mDecodeRequested(false), mIsMultiPartChannel(false), mGotData(false),
|
||||
mIsInCache(false), mBlockingOnload(false)
|
||||
@ -178,7 +178,7 @@ nsresult imgRequest::AddProxy(imgRequestProxy *proxy)
|
||||
// proxies.
|
||||
if (mObservers.IsEmpty()) {
|
||||
NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri.");
|
||||
imgLoader::SetHasProxies(mURI);
|
||||
mLoader->SetHasProxies(mURI);
|
||||
}
|
||||
|
||||
// If we don't have any current observers, we should restart any animation.
|
||||
@ -223,7 +223,7 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, bool
|
||||
if (mCacheEntry) {
|
||||
NS_ABORT_IF_FALSE(mURI, "Removing last observer without key uri.");
|
||||
|
||||
imgLoader::SetHasNoProxies(mURI, mCacheEntry);
|
||||
mLoader->SetHasNoProxies(mURI, mCacheEntry);
|
||||
}
|
||||
#if defined(PR_LOGGING)
|
||||
else {
|
||||
@ -328,9 +328,9 @@ void imgRequest::RemoveFromCache()
|
||||
if (mIsInCache) {
|
||||
// mCacheEntry is nulled out when we have no more observers.
|
||||
if (mCacheEntry)
|
||||
imgLoader::RemoveFromCache(mCacheEntry);
|
||||
mLoader->RemoveFromCache(mCacheEntry);
|
||||
else
|
||||
imgLoader::RemoveFromCache(mURI);
|
||||
mLoader->RemoveFromCache(mURI);
|
||||
}
|
||||
|
||||
mCacheEntry = nullptr;
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
class imgCacheValidator;
|
||||
|
||||
class imgLoader;
|
||||
class imgRequestProxy;
|
||||
class imgCacheEntry;
|
||||
class imgMemoryReporter;
|
||||
@ -50,7 +51,7 @@ class imgRequest : public imgIDecoderObserver,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
{
|
||||
public:
|
||||
imgRequest();
|
||||
imgRequest(imgLoader* aLoader);
|
||||
virtual ~imgRequest();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -183,6 +184,8 @@ public:
|
||||
private:
|
||||
friend class imgMemoryReporter;
|
||||
|
||||
// Weak reference to parent loader; this request cannot outlive its owner.
|
||||
imgLoader* mLoader;
|
||||
nsCOMPtr<nsIRequest> mRequest;
|
||||
// The original URI we were loaded with. This is the same as the URI we are
|
||||
// keyed on in the cache.
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsError.h"
|
||||
#include "imgILoader.h"
|
||||
#include "imgICache.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "imgIEncoder.h"
|
||||
#include "imgIDecoderObserver.h"
|
||||
@ -19,10 +21,14 @@
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "RasterImage.h"
|
||||
|
||||
using namespace mozilla::image;
|
||||
|
||||
class nsIDOMDocument;
|
||||
class nsIDocument;
|
||||
|
||||
/* ========== imgITools implementation ========== */
|
||||
|
||||
|
||||
@ -269,3 +275,20 @@ NS_IMETHODIMP imgTools::GetFirstImageFrame(imgIContainer *aContainer,
|
||||
frame.forget(aSurface);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgTools::GetImgLoaderForDocument(nsIDOMDocument* aDoc, imgILoader** aLoader)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
||||
NS_IF_ADDREF(*aLoader = nsContentUtils::GetImgLoaderForDocument(doc));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgTools::GetImgCacheForDocument(nsIDOMDocument* aDoc, imgICache** aCache)
|
||||
{
|
||||
nsCOMPtr<imgILoader> loader;
|
||||
nsresult rv = GetImgLoaderForDocument(aDoc, getter_AddRefs(loader));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return CallQueryInterface(loader, aCache);
|
||||
}
|
||||
|
@ -7,9 +7,10 @@
|
||||
// Helper function to clear the image cache of content images
|
||||
function clearImageCache()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var imageCache = Components.classes["@mozilla.org/image/cache;1"]
|
||||
.getService(Components.interfaces.imgICache);
|
||||
var tools = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/image/tools;1"]
|
||||
.getService(Components.interfaces.imgITools);
|
||||
var imageCache = tools.getImgCacheForDocument(window.document);
|
||||
imageCache.clearCache(false); // true=chrome, false=content
|
||||
}
|
||||
|
||||
|
@ -85,9 +85,8 @@ function checkSecondLoad()
|
||||
{
|
||||
do_test_pending();
|
||||
|
||||
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
|
||||
var listener = new ImageListener(checkClone, secondLoadDone);
|
||||
requests.push(loader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null));
|
||||
requests.push(gCurrentLoader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null));
|
||||
listener.synchronous = false;
|
||||
}
|
||||
|
||||
@ -139,12 +138,11 @@ function checkSecondChannelLoad()
|
||||
var channellistener = new ChannelListener();
|
||||
channel.asyncOpen(channellistener, null);
|
||||
|
||||
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
|
||||
var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener),
|
||||
getChannelLoadImageStopCallback(channellistener,
|
||||
all_done_callback));
|
||||
var outlistener = {};
|
||||
requests.push(loader.loadImageWithChannel(channel, listener, null, outlistener));
|
||||
requests.push(gCurrentLoader.loadImageWithChannel(channel, listener, null, outlistener));
|
||||
channellistener.outputListener = outlistener.value;
|
||||
|
||||
listener.synchronous = false;
|
||||
@ -152,11 +150,8 @@ function checkSecondChannelLoad()
|
||||
|
||||
function run_loadImageWithChannel_tests()
|
||||
{
|
||||
// To ensure we're testing what we expect to, clear the content image cache
|
||||
// between test runs.
|
||||
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
|
||||
loader.QueryInterface(Ci.imgICache);
|
||||
loader.clearCache(false);
|
||||
// To ensure we're testing what we expect to, create a new loader and cache.
|
||||
gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
||||
|
||||
do_test_pending();
|
||||
|
||||
@ -165,12 +160,11 @@ function run_loadImageWithChannel_tests()
|
||||
var channellistener = new ChannelListener();
|
||||
channel.asyncOpen(channellistener, null);
|
||||
|
||||
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
|
||||
var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener),
|
||||
getChannelLoadImageStopCallback(channellistener,
|
||||
checkSecondChannelLoad));
|
||||
var outlistener = {};
|
||||
requests.push(loader.loadImageWithChannel(channel, listener, null, outlistener));
|
||||
requests.push(gCurrentLoader.loadImageWithChannel(channel, listener, null, outlistener));
|
||||
channellistener.outputListener = outlistener.value;
|
||||
|
||||
listener.synchronous = false;
|
||||
@ -185,12 +179,10 @@ function startImageCallback(otherCb)
|
||||
{
|
||||
return function(listener, request)
|
||||
{
|
||||
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
|
||||
|
||||
// Make sure we can load the same image immediately out of the cache.
|
||||
do_test_pending();
|
||||
var listener2 = new ImageListener(null, function(foo, bar) { do_test_finished(); });
|
||||
requests.push(loader.loadImage(uri, null, null, null, null, listener2, null, 0, null, null, null));
|
||||
requests.push(gCurrentLoader.loadImage(uri, null, null, null, null, listener2, null, 0, null, null, null));
|
||||
listener2.synchronous = false;
|
||||
|
||||
// Now that we've started another load, chain to the callback.
|
||||
@ -198,13 +190,15 @@ function startImageCallback(otherCb)
|
||||
}
|
||||
}
|
||||
|
||||
var gCurrentLoader;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
|
||||
gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
||||
|
||||
do_test_pending();
|
||||
var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone);
|
||||
var req = loader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null);
|
||||
var req = gCurrentLoader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null);
|
||||
requests.push(req);
|
||||
|
||||
// Ensure that we don't cause any mayhem when we lock an image.
|
||||
|
@ -11,7 +11,9 @@ load('image_load_helpers.js');
|
||||
var gHits = 0;
|
||||
|
||||
var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
var gLoader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
|
||||
var gPublicLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
||||
var gPrivateLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
|
||||
gPrivateLoader.QueryInterface(Ci.imgICache).respectPrivacyNotifications();
|
||||
|
||||
function imageHandler(metadata, response) {
|
||||
gHits++;
|
||||
@ -55,7 +57,8 @@ function setup_chan(path, isPrivate, callback) {
|
||||
var listener = new ImageListener(null, callback);
|
||||
listeners.push(listener);
|
||||
var outlistener = {};
|
||||
requests.push(gLoader.loadImageWithChannel(chan, listener, null, outlistener));
|
||||
var loader = isPrivate ? gPrivateLoader : gPublicLoader;
|
||||
requests.push(loader.loadImageWithChannel(chan, listener, null, outlistener));
|
||||
channelListener.outputListener = outlistener.value;
|
||||
listener.synchronous = false;
|
||||
}
|
||||
@ -65,12 +68,12 @@ function loadImage(isPrivate, callback) {
|
||||
var uri = gIoService.newURI(gImgPath, null, null);
|
||||
var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup);
|
||||
loadGroup.notificationCallbacks = new NotificationCallbacks(isPrivate);
|
||||
requests.push(gLoader.loadImage(uri, null, null, null, loadGroup, listener, null, 0, null, null, null));
|
||||
var loader = isPrivate ? gPrivateLoader : gPublicLoader;
|
||||
requests.push(loader.loadImage(uri, null, null, null, loadGroup, listener, null, 0, null, null, null));
|
||||
listener.synchronous = false;
|
||||
}
|
||||
|
||||
function run_loadImage_tests() {
|
||||
clearAllImageCaches();
|
||||
let cs = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
|
||||
cs.evictEntries(Ci.nsICache.STORE_ANYWHERE);
|
||||
|
||||
@ -80,21 +83,14 @@ function run_loadImage_tests() {
|
||||
loadImage(true, function() {
|
||||
loadImage(true, function() {
|
||||
do_check_eq(gHits, 2);
|
||||
do_test_finished();
|
||||
server.stop(do_test_finished);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function clearAllImageCaches() {
|
||||
gLoader.QueryInterface(Ci.imgICache);
|
||||
gLoader.clearCache(false, false);
|
||||
gLoader.clearCache(false, true);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
clearAllImageCaches();
|
||||
do_test_pending();
|
||||
|
||||
// We create a public channel that loads an image, then an identical
|
||||
|
@ -481,7 +481,7 @@ nsContentDLF::CreateXULDocument(const char* aCommand,
|
||||
}
|
||||
|
||||
bool nsContentDLF::IsImageContentType(const char* aContentType) {
|
||||
nsCOMPtr<imgILoader> loader(do_GetService("@mozilla.org/image/loader;1"));
|
||||
nsCOMPtr<imgILoader> loader(do_CreateInstance("@mozilla.org/image/loader;1"));
|
||||
bool isDecoderAvailable = false;
|
||||
loader->SupportImageWithMimeType(aContentType, &isDecoderAvailable);
|
||||
return isDecoderAvailable;
|
||||
|
@ -1786,8 +1786,8 @@ nsImageFrame::LoadIcon(const nsAString& aSpec,
|
||||
nsCOMPtr<nsIURI> realURI;
|
||||
SpecToURI(aSpec, sIOService, getter_AddRefs(realURI));
|
||||
|
||||
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<imgILoader> il =
|
||||
nsContentUtils::GetImgLoaderForDocument(aPresContext->Document());
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "gfxImageSurface.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
static const uint32_t kIconWidth = 16;
|
||||
static const uint32_t kIconHeight = 16;
|
||||
@ -278,10 +279,8 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = document->GetDocumentLoadGroup();
|
||||
if (!loadGroup) return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsCOMPtr<imgILoader> loader = do_GetService("@mozilla.org/image/loader;1",
|
||||
&rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<imgILoader> loader = nsContentUtils::GetImgLoaderForDocument(document);
|
||||
if (!loader) return NS_ERROR_FAILURE;
|
||||
|
||||
if (!mSetIcon) {
|
||||
// Set a completely transparent 16x16 image as the icon on this menu item
|
||||
@ -306,9 +305,9 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
|
||||
|
||||
// Passing in null for channelPolicy here since nsMenuItemIconX::LoadIcon is
|
||||
// not exposed to web content
|
||||
rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, loadGroup, this,
|
||||
nullptr, nsIRequest::LOAD_NORMAL, nullptr, nullptr,
|
||||
nullptr, getter_AddRefs(mIconRequest));
|
||||
nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, loadGroup, this,
|
||||
nullptr, nsIRequest::LOAD_NORMAL, nullptr, nullptr,
|
||||
nullptr, getter_AddRefs(mIconRequest));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// We need to request the icon be decoded (bug 573583, bug 705516).
|
||||
|
Loading…
Reference in New Issue
Block a user