Back out bug 722861.

This commit is contained in:
Josh Matthews 2012-08-27 15:31:29 -04:00
parent 17c6b7c738
commit 1210ea94dd
23 changed files with 195 additions and 484 deletions

View File

@ -482,6 +482,13 @@ public:
return sIOService;
}
static imgILoader* GetImgLoader()
{
if (!sImgLoaderInitialized)
InitImgLoader();
return sImgLoader;
}
#ifdef MOZ_XTF
static nsIXTFService* GetXTFService();
#endif
@ -656,17 +663,10 @@ 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, nsIDocument* aDocument);
static bool IsImageInCache(nsIURI* aURI);
/**
* Method to get an imgIContainer from an image loading content
@ -2160,11 +2160,9 @@ private:
static bool sImgLoaderInitialized;
static void InitImgLoader();
// The following four members are initialized lazily
// The following two members are initialized lazily
static imgILoader* sImgLoader;
static imgILoader* sPrivateImgLoader;
static imgICache* sImgCache;
static imgICache* sPrivateImgCache;
static nsIConsoleService* sConsoleService;

View File

@ -50,7 +50,6 @@ EXPORTS_mozilla/dom = \
$(NULL)
LOCAL_INCLUDES = \
-I$(topsrcdir)/image/src \
$(NULL)
CPPSRCS = \

View File

@ -119,7 +119,6 @@ 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"
@ -135,7 +134,6 @@ 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"
@ -189,9 +187,7 @@ 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;
@ -512,17 +508,15 @@ nsContentUtils::InitImgLoader()
sImgLoaderInitialized = true;
// Ignore failure and just don't load images
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();
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;
}
}
bool
@ -1499,9 +1493,7 @@ 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
@ -2700,60 +2692,19 @@ 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, nsIDocument* aDocument)
nsContentUtils::IsImageInCache(nsIURI* aURI)
{
if (!sImgLoaderInitialized)
InitImgLoader();
imgILoader* loader = GetImgLoaderForDocument(aDocument);
nsCOMPtr<imgICache> cache = do_QueryInterface(loader);
if (!sImgCache) return false;
// 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 = cache->FindEntryProperties(aURI, getter_AddRefs(props));
nsresult rv = sImgCache->FindEntryProperties(aURI, getter_AddRefs(props));
return (NS_SUCCEEDED(rv) && props);
}
@ -2769,7 +2720,7 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
NS_PRECONDITION(aRequest, "Null out param");
imgILoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
imgILoader* imgLoader = GetImgLoader();
if (!imgLoader) {
// nothing we can do here
return NS_OK;

View File

@ -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, static_cast<nsIDocument *>(this)) ||
if (nsContentUtils::IsImageInCache(uri) ||
!nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this),
this, NodePrincipal(), &blockingStatus)) {
return;

View File

@ -88,7 +88,7 @@ nsImageLoadingContent::nsImageLoadingContent()
mCurrentRequestRegistered(false),
mPendingRequestRegistered(false)
{
if (!nsContentUtils::GetImgLoaderForChannel(nullptr)) {
if (!nsContentUtils::GetImgLoader()) {
mLoadingEnabled = false;
}
}
@ -334,7 +334,7 @@ nsImageLoadingContent::SetLoadingEnabled(bool aLoadingEnabled)
{
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
if (nsContentUtils::GetImgLoaderForChannel(nullptr)) {
if (nsContentUtils::GetImgLoader()) {
mLoadingEnabled = aLoadingEnabled;
}
return NS_OK;
@ -518,7 +518,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
{
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
if (!nsContentUtils::GetImgLoaderForChannel(aChannel)) {
if (!nsContentUtils::GetImgLoader()) {
return NS_ERROR_NULL_POINTER;
}
@ -537,7 +537,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
// Do the load.
nsCOMPtr<imgIRequest>& req = PrepareNextRequest();
nsresult rv = nsContentUtils::GetImgLoaderForChannel(aChannel)->
nsresult rv = nsContentUtils::GetImgLoader()->
LoadImageWithChannel(aChannel, this, doc, aListener,
getter_AddRefs(req));
if (NS_SUCCEEDED(rv)) {

View File

@ -477,7 +477,7 @@ URIEquals(nsIURI *a, nsIURI *b)
static bool
IsSupportedImage(const nsCString& aMimeType)
{
nsCOMPtr<imgILoader> loader = nsContentUtils::GetImgLoaderForChannel(nullptr);
imgILoader* loader = nsContentUtils::GetImgLoader();
if (!loader) {
return false;
}

View File

@ -24,9 +24,9 @@ nsWebNavigationInfo::Init()
mCategoryManager = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
mImgLoader = nsContentUtils::GetImgLoaderForChannel(nullptr);
mImgLoader = do_GetService("@mozilla.org/image/loader;1", &rv);
return NS_OK;
return rv;
}
NS_IMETHODIMP

View File

@ -301,7 +301,8 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR
NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);
nsCOMPtr<imgILoader> il(do_CreateInstance("@mozilla.org/image/loader;1"));
nsCOMPtr<imgILoader> il(do_GetService(
"@mozilla.org/image/loader;1"));
NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);
return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr,

View File

@ -96,7 +96,7 @@ static nsresult
imglib_Initialize()
{
mozilla::image::DiscardTracker::Initialize();
imgLoader::GlobalInit();
imgLoader::InitCache();
return NS_OK;
}

View File

@ -17,7 +17,7 @@ interface nsIProperties;
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(b06e0fa5-d6e2-4fa3-8fc0-7775aed96522)]
[scriptable, uuid(f1b74aae-5661-4753-a21c-66dd644afebc)]
interface imgICache : nsISupports
{
/**
@ -49,11 +49,4 @@ 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();
};

View File

@ -8,11 +8,8 @@
interface nsIInputStream;
interface imgIContainer;
interface imgILoader;
interface imgICache;
interface nsIDOMDocument;
[scriptable, uuid(53dd1cbe-cb9f-4d9e-8104-1ab72851c88e)]
[scriptable, uuid(8e16f39e-7012-46bd-aa22-2a7a3265608f)]
interface imgITools : nsISupports
{
/**
@ -74,26 +71,6 @@ 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

View File

@ -50,6 +50,7 @@
#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.
@ -57,7 +58,6 @@
#include "nsIHttpChannelInternal.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIChannelPolicy.h"
#include "nsILoadContext.h"
#include "nsContentUtils.h"
@ -87,11 +87,8 @@ public:
{
AllSizes chrome;
AllSizes content;
for (PRUint32 i = 0; i < mKnownLoaders.Length(); i++) {
mKnownLoaders[i]->mChromeCache.EnumerateRead(EntryAllSizes, &chrome);
mKnownLoaders[i]->mCache.EnumerateRead(EntryAllSizes, &content);
}
imgLoader::sChromeCache.EnumerateRead(EntryAllSizes, &chrome);
imgLoader::sCache.EnumerateRead(EntryAllSizes, &content);
#define REPORT(_path, _kind, _amount, _desc) \
do { \
@ -158,10 +155,8 @@ public:
NS_IMETHOD GetExplicitNonHeap(int64_t *n)
{
size_t n2 = 0;
for (PRUint32 i = 0; i < mKnownLoaders.Length(); i++) {
mKnownLoaders[i]->mChromeCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
mKnownLoaders[i]->mCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
}
imgLoader::sChromeCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
imgLoader::sCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
*n = n2;
return NS_OK;
}
@ -169,25 +164,11 @@ public:
static int64_t GetImagesContentUsedUncompressed()
{
size_t n = 0;
for (PRUint32 i = 0; i < imgLoader::sMemReporter->mKnownLoaders.Length(); i++) {
imgLoader::sMemReporter->mKnownLoaders[i]->mCache.EnumerateRead(EntryUsedUncompressedSize, &n);
}
imgLoader::sCache.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;
@ -358,11 +339,11 @@ nsProgressNotificationProxy::GetInterface(const nsIID& iid,
return NS_NOINTERFACE;
}
static void NewRequestAndEntry(bool aForcePrincipalCheckForCacheEntry, imgLoader* aLoader,
static void NewRequestAndEntry(bool aForcePrincipalCheckForCacheEntry,
imgRequest **aRequest, imgCacheEntry **aEntry)
{
nsRefPtr<imgRequest> request = new imgRequest(aLoader);
nsRefPtr<imgCacheEntry> entry = new imgCacheEntry(aLoader, request, aForcePrincipalCheckForCacheEntry);
nsRefPtr<imgRequest> request = new imgRequest();
nsRefPtr<imgCacheEntry> entry = new imgCacheEntry(request, aForcePrincipalCheckForCacheEntry);
request.forget(aRequest);
entry.forget(aEntry);
}
@ -530,9 +511,8 @@ static uint32_t SecondsFromPRTime(PRTime prTime)
return uint32_t(int64_t(prTime) / int64_t(PR_USEC_PER_SEC));
}
imgCacheEntry::imgCacheEntry(imgLoader* loader, imgRequest *request, bool forcePrincipalCheck)
: mLoader(loader),
mRequest(request),
imgCacheEntry::imgCacheEntry(imgRequest *request, bool forcePrincipalCheck)
: mRequest(request),
mDataSize(0),
mTouchedTime(SecondsFromPRTime(PR_Now())),
mExpiryTime(0),
@ -566,7 +546,7 @@ void imgCacheEntry::UpdateCache(int32_t diff /* = 0 */)
if (!Evicted() && HasNoProxies()) {
nsCOMPtr<nsIURI> uri;
mRequest->GetURI(getter_AddRefs(uri));
mLoader->CacheEntriesChanged(uri, diff);
imgLoader::CacheEntriesChanged(uri, diff);
}
}
@ -726,6 +706,8 @@ class imgCacheObserver MOZ_FINAL : public nsIObserver
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
imgLoader mLoader;
};
NS_IMPL_ISUPPORTS1(imgCacheObserver, nsIObserver)
@ -735,6 +717,10 @@ 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;
}
@ -774,44 +760,45 @@ void imgCacheExpirationTracker::NotifyExpired(imgCacheEntry *entry)
// We can be called multiple times on the same entry. Don't do work multiple
// times.
if (!entry->Evicted())
entry->Loader()->RemoveFromCache(entry);
imgLoader::RemoveFromCache(entry);
entry->Loader()->VerifyCacheSizes();
imgLoader::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)
{
sMemReporter->AddRef();
sMemReporter->RegisterLoader(this);
/* member initializers and constructor code */
}
imgLoader::~imgLoader()
{
ClearChromeImageCache();
ClearImageCache();
sMemReporter->UnregisterLoader(this);
sMemReporter->Release();
/* destructor code */
}
void imgLoader::VerifyCacheSizes()
{
#ifdef DEBUG
if (!mCacheTracker)
if (!gCacheTracker)
return;
uint32_t cachesize = mCache.Count() + mChromeCache.Count();
uint32_t queuesize = mCacheQueue.GetNumElements() + mChromeCacheQueue.GetNumElements();
uint32_t cachesize = sCache.Count() + sChromeCache.Count();
uint32_t queuesize = sCacheQueue.GetNumElements() + sChromeCacheQueue.GetNumElements();
uint32_t trackersize = 0;
for (nsExpirationTracker<imgCacheEntry, 3>::Iterator it(mCacheTracker); it.Next(); )
for (nsExpirationTracker<imgCacheEntry, 3>::Iterator it(gCacheTracker); 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!");
@ -823,9 +810,9 @@ imgLoader::imgCacheTable & imgLoader::GetCache(nsIURI *aURI)
bool chrome = false;
aURI->SchemeIs("chrome", &chrome);
if (chrome)
return mChromeCache;
return sChromeCache;
else
return mCache;
return sCache;
}
imgCacheQueue & imgLoader::GetCacheQueue(nsIURI *aURI)
@ -833,22 +820,34 @@ imgCacheQueue & imgLoader::GetCacheQueue(nsIURI *aURI)
bool chrome = false;
aURI->SchemeIs("chrome", &chrome);
if (chrome)
return mChromeCacheQueue;
return sChromeCacheQueue;
else
return mCacheQueue;
return sCacheQueue;
}
void imgLoader::GlobalInit()
nsresult imgLoader::InitCache()
{
NS_TIME_FUNCTION;
nsresult rv;
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (!os)
return NS_ERROR_FAILURE;
gCacheObserver = new imgCacheObserver();
NS_ADDREF(gCacheObserver);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os)
os->AddObserver(gCacheObserver, "memory-pressure", false);
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();
int32_t timeweight;
nsresult rv = Preferences::GetInt("image.cache.timeweight", &timeweight);
rv = Preferences::GetInt("image.cache.timeweight", &timeweight);
if (NS_SUCCEEDED(rv))
sCacheTimeWeight = timeweight / 1000.0;
else
@ -861,51 +860,23 @@ void imgLoader::GlobalInit()
else
sCacheMaxSize = 5 * 1024 * 1024;
sMemReporter = new imgMemoryReporter();
NS_RegisterMemoryMultiReporter(sMemReporter);
NS_RegisterMemoryMultiReporter(new imgMemoryReporter());
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");
return NS_OK;
}
// 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);
NS_IMETHODIMP
imgLoader::RespectPrivacyNotifications()
{
mRespectPrivacy = true;
return NS_OK;
}
@ -917,21 +888,12 @@ imgLoader::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* a
if (!strcmp(NS_ConvertUTF16toUTF8(aData).get(), "image.http.accept")) {
ReadAcceptHeaderPref();
}
}
} 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) {
// ...and exits from private browsing.
else if (!strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC)) {
if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData))
ClearImageCache();
ClearChromeImageCache();
}
} else if (strcmp(aTopic, "profile-before-change") == 0 ||
strcmp(aTopic, "xpcom-shutdown") == 0) {
mCacheTracker = nullptr;
}
// (Nothing else should bring us here)
@ -980,8 +942,8 @@ NS_IMETHODIMP imgLoader::FindEntryProperties(nsIURI *uri, nsIProperties **_retva
*_retval = nullptr;
if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
if (mCacheTracker && entry->HasNoProxies())
mCacheTracker->MarkUsed(entry);
if (gCacheTracker && entry->HasNoProxies())
gCacheTracker->MarkUsed(entry);
nsRefPtr<imgRequest> request = getter_AddRefs(entry->GetRequest());
if (request) {
@ -995,23 +957,27 @@ NS_IMETHODIMP imgLoader::FindEntryProperties(nsIURI *uri, nsIProperties **_retva
void imgLoader::Shutdown()
{
NS_RELEASE(gCacheObserver);
ClearChromeImageCache();
ClearImageCache();
NS_IF_RELEASE(gCacheObserver);
delete gCacheTracker;
gCacheTracker = nullptr;
}
nsresult imgLoader::ClearChromeImageCache()
{
return EvictEntries(mChromeCache);
return EvictEntries(sChromeCache);
}
nsresult imgLoader::ClearImageCache()
{
return EvictEntries(mCache);
return EvictEntries(sCache);
}
void imgLoader::MinimizeCaches()
{
EvictEntries(mCacheQueue);
EvictEntries(mChromeCacheQueue);
EvictEntries(sCacheQueue);
EvictEntries(sChromeCacheQueue);
}
bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
@ -1054,8 +1020,8 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
if (entry->HasNoProxies()) {
nsresult addrv = NS_OK;
if (mCacheTracker)
addrv = mCacheTracker->AddObject(entry);
if (gCacheTracker)
addrv = gCacheTracker->AddObject(entry);
if (NS_SUCCEEDED(addrv)) {
imgCacheQueue &queue = GetCacheQueue(key);
@ -1085,8 +1051,8 @@ bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
nsresult addrv = NS_OK;
if (mCacheTracker)
addrv = mCacheTracker->AddObject(entry);
if (gCacheTracker)
addrv = gCacheTracker->AddObject(entry);
if (NS_SUCCEEDED(addrv)) {
queue.Push(entry);
@ -1115,8 +1081,8 @@ bool imgLoader::SetHasProxies(nsIURI *key)
imgCacheQueue &queue = GetCacheQueue(key);
queue.Remove(entry);
if (mCacheTracker)
mCacheTracker->RemoveObject(entry);
if (gCacheTracker)
gCacheTracker->RemoveObject(entry);
entry->SetHasNoProxies(false);
@ -1241,7 +1207,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
return false;
nsRefPtr<imgCacheValidator> hvc =
new imgCacheValidator(progressproxy, this, request, aCX, forcePrincipalCheck);
new imgCacheValidator(progressproxy, request, aCX, forcePrincipalCheck);
nsCOMPtr<nsIStreamListener> listener = hvc.get();
@ -1422,8 +1388,8 @@ bool imgLoader::RemoveFromCache(nsIURI *aKey)
// Entries with no proxies are in the tracker.
if (entry->HasNoProxies()) {
if (mCacheTracker)
mCacheTracker->RemoveObject(entry);
if (gCacheTracker)
gCacheTracker->RemoveObject(entry);
queue.Remove(entry);
}
@ -1457,8 +1423,8 @@ bool imgLoader::RemoveFromCache(imgCacheEntry *entry)
if (entry->HasNoProxies()) {
LOG_STATIC_FUNC(gImgLog, "imgLoader::RemoveFromCache removing from tracker");
if (mCacheTracker)
mCacheTracker->RemoveObject(entry);
if (gCacheTracker)
gCacheTracker->RemoveObject(entry);
queue.Remove(entry);
}
@ -1558,25 +1524,6 @@ 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);
@ -1630,8 +1577,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
NS_ABORT_IF_FALSE(!request->HasCacheEntry(), "Proxyless entry's request has cache entry!");
request->SetCacheEntry(entry);
if (mCacheTracker)
mCacheTracker->MarkUsed(entry);
if (gCacheTracker)
gCacheTracker->MarkUsed(entry);
}
entry->Touch();
@ -1668,13 +1615,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
#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));
NewRequestAndEntry(forcePrincipalCheck, 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()));
@ -1799,12 +1741,6 @@ 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;
@ -1862,8 +1798,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 (mCacheTracker)
mCacheTracker->MarkUsed(entry);
if (gCacheTracker)
gCacheTracker->MarkUsed(entry);
}
}
}
@ -1890,7 +1826,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, this, getter_AddRefs(request), getter_AddRefs(entry));
NewRequestAndEntry(true, getter_AddRefs(request), getter_AddRefs(entry));
// We use originalURI here to fulfil the imgIRequest contract on GetURI.
nsCOMPtr<nsIURI> originalURI;
@ -2102,16 +2038,17 @@ NS_IMPL_ISUPPORTS5(imgCacheValidator, nsIStreamListener, nsIRequestObserver,
nsIChannelEventSink, nsIInterfaceRequestor,
nsIAsyncVerifyRedirectCallback)
imgLoader imgCacheValidator::sImgLoader;
imgCacheValidator::imgCacheValidator(nsProgressNotificationProxy* progress,
imgLoader* loader, imgRequest *request,
void *aContext, bool forcePrincipalCheckForCacheEntry)
imgRequest *request, void *aContext,
bool forcePrincipalCheckForCacheEntry)
: mProgressProxy(progress),
mRequest(request),
mContext(aContext),
mImgLoader(loader)
mContext(aContext)
{
NewRequestAndEntry(forcePrincipalCheckForCacheEntry, loader, getter_AddRefs(mNewRequest),
getter_AddRefs(mNewEntry));
NewRequestAndEntry(forcePrincipalCheckForCacheEntry,
getter_AddRefs(mNewRequest), getter_AddRefs(mNewEntry));
}
imgCacheValidator::~imgCacheValidator()
@ -2214,7 +2151,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.
mImgLoader->PutIntoCache(originalURI, mNewEntry);
sImgLoader.PutIntoCache(originalURI, mNewEntry);
uint32_t count = mProxies.Count();
for (int32_t i = count-1; i>=0; i--) {

View File

@ -27,19 +27,16 @@
#include "prlock.h"
#endif
class imgLoader;
class imgRequest;
class imgRequestProxy;
class imgIRequest;
class imgIDecoderObserver;
class nsILoadGroup;
class imgCacheExpirationTracker;
class imgMemoryReporter;
class imgCacheEntry
{
public:
imgCacheEntry(imgLoader* loader, imgRequest *request, bool aForcePrincipalCheck);
imgCacheEntry(imgRequest *request, bool aForcePrincipalCheck);
~imgCacheEntry();
nsrefcnt AddRef()
@ -133,11 +130,6 @@ public:
return mForcePrincipalCheck;
}
imgLoader* Loader() const
{
return mLoader;
}
private: // methods
friend class imgLoader;
friend class imgCacheQueue;
@ -156,7 +148,6 @@ private: // data
nsAutoRefCnt mRefCnt;
NS_DECL_OWNINGTHREAD
imgLoader* mLoader;
nsRefPtr<imgRequest> mRequest;
uint32_t mDataSize;
int32_t mTouchedTime;
@ -228,19 +219,18 @@ 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
nsresult ClearChromeImageCache();
nsresult ClearImageCache();
void MinimizeCaches();
static nsresult ClearChromeImageCache();
static nsresult ClearImageCache();
static void MinimizeCaches();
nsresult InitCache();
static nsresult InitCache();
bool RemoveFromCache(nsIURI *aKey);
bool RemoveFromCache(imgCacheEntry *entry);
static bool RemoveFromCache(nsIURI *aKey);
static bool RemoveFromCache(imgCacheEntry *entry);
bool PutIntoCache(nsIURI *key, imgCacheEntry *entry);
static bool PutIntoCache(nsIURI *key, imgCacheEntry *entry);
// Returns true if we should prefer evicting cache entry |two| over cache
// entry |one|.
@ -266,7 +256,7 @@ public:
return oneweight < twoweight;
}
void VerifyCacheSizes();
static 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
@ -279,8 +269,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.
bool SetHasNoProxies(nsIURI *key, imgCacheEntry *entry);
bool SetHasProxies(nsIURI *key);
static bool SetHasNoProxies(nsIURI *key, imgCacheEntry *entry);
static bool SetHasProxies(nsIURI *key);
private: // methods
@ -317,32 +307,27 @@ private: // methods
typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
nsresult EvictEntries(imgCacheTable &aCacheToClear);
nsresult EvictEntries(imgCacheQueue &aQueueToClear);
static nsresult EvictEntries(imgCacheTable &aCacheToClear);
static nsresult EvictEntries(imgCacheQueue &aQueueToClear);
imgCacheTable &GetCache(nsIURI *aURI);
imgCacheQueue &GetCacheQueue(nsIURI *aURI);
void CacheEntriesChanged(nsIURI *aURI, PRInt32 sizediff = 0);
void CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue);
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);
private: // data
friend class imgCacheEntry;
friend class imgMemoryReporter;
imgCacheTable mCache;
imgCacheQueue mCacheQueue;
imgCacheTable mChromeCache;
imgCacheQueue mChromeCacheQueue;
static imgCacheTable sCache;
static imgCacheQueue sCacheQueue;
static imgCacheTable sChromeCache;
static imgCacheQueue sChromeCacheQueue;
static double sCacheTimeWeight;
static uint32_t sCacheMaxSize;
static imgMemoryReporter* sMemReporter;
nsCString mAcceptHeader;
nsAutoPtr<imgCacheExpirationTracker> mCacheTracker;
bool mRespectPrivacy;
};
@ -410,8 +395,8 @@ class imgCacheValidator : public nsIStreamListener,
public nsIAsyncVerifyRedirectCallback
{
public:
imgCacheValidator(nsProgressNotificationProxy* progress, imgLoader* loader,
imgRequest *request, void *aContext, bool forcePrincipalCheckForCacheEntry);
imgCacheValidator(nsProgressNotificationProxy* progress, imgRequest *request,
void *aContext, bool forcePrincipalCheckForCacheEntry);
virtual ~imgCacheValidator();
void AddProxy(imgRequestProxy *aProxy);
@ -437,7 +422,7 @@ private:
void *mContext;
imgLoader* mImgLoader;
static imgLoader sImgLoader;
};
#endif // imgLoader_h__

View File

@ -79,8 +79,8 @@ NS_IMPL_ISUPPORTS8(imgRequest,
nsIInterfaceRequestor,
nsIAsyncVerifyRedirectCallback)
imgRequest::imgRequest(imgLoader* aLoader) :
mLoader(aLoader), mValidator(nullptr), mImageSniffers("image-sniffing-services"),
imgRequest::imgRequest() :
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.");
mLoader->SetHasProxies(mURI);
imgLoader::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.");
mLoader->SetHasNoProxies(mURI, mCacheEntry);
imgLoader::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)
mLoader->RemoveFromCache(mCacheEntry);
imgLoader::RemoveFromCache(mCacheEntry);
else
mLoader->RemoveFromCache(mURI);
imgLoader::RemoveFromCache(mURI);
}
mCacheEntry = nullptr;

View File

@ -31,7 +31,6 @@
class imgCacheValidator;
class imgLoader;
class imgRequestProxy;
class imgCacheEntry;
class imgMemoryReporter;
@ -51,7 +50,7 @@ class imgRequest : public imgIDecoderObserver,
public nsIAsyncVerifyRedirectCallback
{
public:
imgRequest(imgLoader* aLoader);
imgRequest();
virtual ~imgRequest();
NS_DECL_ISUPPORTS
@ -184,8 +183,6 @@ 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.

View File

@ -8,8 +8,6 @@
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsError.h"
#include "imgILoader.h"
#include "imgICache.h"
#include "imgIContainer.h"
#include "imgIEncoder.h"
#include "imgIDecoderObserver.h"
@ -21,14 +19,10 @@
#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 ========== */
@ -275,20 +269,3 @@ 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);
}

View File

@ -7,10 +7,9 @@
// Helper function to clear the image cache of content images
function clearImageCache()
{
var tools = SpecialPowers.wrap(Components)
.classes["@mozilla.org/image/tools;1"]
.getService(Components.interfaces.imgITools);
var imageCache = tools.getImgCacheForDocument(window.document);
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var imageCache = Components.classes["@mozilla.org/image/cache;1"]
.getService(Components.interfaces.imgICache);
imageCache.clearCache(false); // true=chrome, false=content
}

View File

@ -85,8 +85,9 @@ function checkSecondLoad()
{
do_test_pending();
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
var listener = new ImageListener(checkClone, secondLoadDone);
requests.push(gCurrentLoader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null));
requests.push(loader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null));
listener.synchronous = false;
}
@ -138,11 +139,12 @@ 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(gCurrentLoader.loadImageWithChannel(channel, listener, null, outlistener));
requests.push(loader.loadImageWithChannel(channel, listener, null, outlistener));
channellistener.outputListener = outlistener.value;
listener.synchronous = false;
@ -150,8 +152,11 @@ function checkSecondChannelLoad()
function run_loadImageWithChannel_tests()
{
// 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);
// 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);
do_test_pending();
@ -160,11 +165,12 @@ 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(gCurrentLoader.loadImageWithChannel(channel, listener, null, outlistener));
requests.push(loader.loadImageWithChannel(channel, listener, null, outlistener));
channellistener.outputListener = outlistener.value;
listener.synchronous = false;
@ -179,10 +185,12 @@ 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(gCurrentLoader.loadImage(uri, null, null, null, null, listener2, null, 0, null, null, null));
requests.push(loader.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.
@ -190,15 +198,13 @@ function startImageCallback(otherCb)
}
}
var gCurrentLoader;
function run_test()
{
gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
var loader = Cc["@mozilla.org/image/loader;1"].getService(Ci.imgILoader);
do_test_pending();
var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone);
var req = gCurrentLoader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null);
var req = loader.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.

View File

@ -1,109 +0,0 @@
do_load_httpd_js();
var server = new nsHttpServer();
server.registerPathHandler('/image.png', imageHandler);
server.start(8088);
load('image_load_helpers.js');
var gHits = 0;
var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
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++;
response.setHeader("Cache-Control", "max-age=10000", false);
response.setStatusLine(metadata.httpVersion, 200, "OK");
response.setHeader("Content-Type", "image/png", false);
var body = "iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=";
response.bodyOutputStream.write(body, body.length);
}
var requests = [];
var listeners = [];
function NotificationCallbacks(isPrivate) {
this.usePrivateBrowsing = isPrivate;
}
NotificationCallbacks.prototype = {
QueryInterface: function (iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsILoadContext))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
getInterface: function(iid) {
if (iid.equals(Ci.nsILoadContext))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
var gImgPath = 'http://localhost:8088/image.png';
function setup_chan(path, isPrivate, callback) {
var uri = gIoService.newURI(gImgPath, null, null);
var chan = gIoService.newChannelFromURI(uri);
chan.notificationCallbacks = new NotificationCallbacks(isPrivate);
var channelListener = new ChannelListener();
chan.asyncOpen(channelListener, null);
var listener = new ImageListener(null, callback);
listeners.push(listener);
var outlistener = {};
var loader = isPrivate ? gPrivateLoader : gPublicLoader;
requests.push(loader.loadImageWithChannel(chan, listener, null, outlistener));
channelListener.outputListener = outlistener.value;
listener.synchronous = false;
}
function loadImage(isPrivate, callback) {
var listener = new ImageListener(null, 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);
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() {
let cs = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService);
cs.evictEntries(Ci.nsICache.STORE_ANYWHERE);
gHits = 0;
loadImage(false, function() {
loadImage(false, function() {
loadImage(true, function() {
loadImage(true, function() {
do_check_eq(gHits, 2);
server.stop(do_test_finished);
});
});
});
});
}
function run_test() {
do_test_pending();
// We create a public channel that loads an image, then an identical
// one that should cause a cache read. We then create a private channel
// and load the same image, and do that a second time to ensure a cache
// read. In total, we should cause two separate http responses to occur,
// since the private channels shouldn't be able to use the public cache.
setup_chan('/image.png', false, function() {
setup_chan('/image.png', false, function() {
setup_chan('/image.png', true, function() {
setup_chan('/image.png', true, function() {
do_check_eq(gHits, 2);
run_loadImage_tests();
});
});
});
});
}

View File

@ -11,4 +11,3 @@ tail =
# Bug 676968: test fails consistently on Android
fail-if = os == "android"
[test_moz_icon_uri.js]
[test_private_channel.js]

View File

@ -481,7 +481,7 @@ nsContentDLF::CreateXULDocument(const char* aCommand,
}
bool nsContentDLF::IsImageContentType(const char* aContentType) {
nsCOMPtr<imgILoader> loader(do_CreateInstance("@mozilla.org/image/loader;1"));
nsCOMPtr<imgILoader> loader(do_GetService("@mozilla.org/image/loader;1"));
bool isDecoderAvailable = false;
loader->SupportImageWithMimeType(aContentType, &isDecoderAvailable);
return isDecoderAvailable;

View File

@ -1786,8 +1786,8 @@ nsImageFrame::LoadIcon(const nsAString& aSpec,
nsCOMPtr<nsIURI> realURI;
SpecToURI(aSpec, sIOService, getter_AddRefs(realURI));
nsCOMPtr<imgILoader> il =
nsContentUtils::GetImgLoaderForDocument(aPresContext->Document());
nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1", &rv));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(aPresContext, getter_AddRefs(loadGroup));

View File

@ -29,7 +29,6 @@
#include "gfxImageSurface.h"
#include "imgIContainer.h"
#include "nsCocoaUtils.h"
#include "nsContentUtils.h"
static const uint32_t kIconWidth = 16;
static const uint32_t kIconHeight = 16;
@ -279,8 +278,10 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
nsCOMPtr<nsILoadGroup> loadGroup = document->GetDocumentLoadGroup();
if (!loadGroup) return NS_ERROR_FAILURE;
nsCOMPtr<imgILoader> loader = nsContentUtils::GetImgLoaderForDocument(document);
if (!loader) 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;
if (!mSetIcon) {
// Set a completely transparent 16x16 image as the icon on this menu item
@ -305,9 +306,9 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
// Passing in null for channelPolicy here since nsMenuItemIconX::LoadIcon is
// not exposed to web content
nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, loadGroup, this,
nullptr, nsIRequest::LOAD_NORMAL, nullptr, nullptr,
nullptr, getter_AddRefs(mIconRequest));
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).