diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 9a7e7c421909..3beee8ed00e7 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -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; diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index 76c7c7b3f8bd..b424893a3e1a 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -50,7 +50,6 @@ EXPORTS_mozilla/dom = \ $(NULL) LOCAL_INCLUDES = \ - -I$(topsrcdir)/image/src \ $(NULL) CPPSRCS = \ diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index e79bb765a2ce..ff256552fb8a 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -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* nsContentUtils::sAtomEventTable = nullptr; nsDataHashtable* 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 loadGroup = aDoc->GetDocumentLoadGroup(); - nsCOMPtr callbacks; - if (loadGroup) { - loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); - if (callbacks) { - nsCOMPtr loadContext = do_GetInterface(callbacks); - isPrivate = loadContext && loadContext->UsePrivateBrowsing(); - } - } else { - nsCOMPtr channel = aDoc->GetChannel(); - if (channel) { - nsCOMPtr 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 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 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 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; diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 71e737819334..68201941d5ac 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -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(this)) || + if (nsContentUtils::IsImageInCache(uri) || !nsContentUtils::CanLoadImage(uri, static_cast(this), this, NodePrincipal(), &blockingStatus)) { return; diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index 3ab8ce77bc73..7e1d39a8a5c1 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -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& req = PrepareNextRequest(); - nsresult rv = nsContentUtils::GetImgLoaderForChannel(aChannel)-> + nsresult rv = nsContentUtils::GetImgLoader()-> LoadImageWithChannel(aChannel, this, doc, aListener, getter_AddRefs(req)); if (NS_SUCCEEDED(rv)) { diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index bb731007164d..9da9f88e8f8c 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -477,7 +477,7 @@ URIEquals(nsIURI *a, nsIURI *b) static bool IsSupportedImage(const nsCString& aMimeType) { - nsCOMPtr loader = nsContentUtils::GetImgLoaderForChannel(nullptr); + imgILoader* loader = nsContentUtils::GetImgLoader(); if (!loader) { return false; } diff --git a/docshell/base/nsWebNavigationInfo.cpp b/docshell/base/nsWebNavigationInfo.cpp index 1567bc873be0..30b42e846008 100644 --- a/docshell/base/nsWebNavigationInfo.cpp +++ b/docshell/base/nsWebNavigationInfo.cpp @@ -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 diff --git a/embedding/browser/webBrowser/nsContextMenuInfo.cpp b/embedding/browser/webBrowser/nsContextMenuInfo.cpp index 492faa474fc9..0a994274af66 100644 --- a/embedding/browser/webBrowser/nsContextMenuInfo.cpp +++ b/embedding/browser/webBrowser/nsContextMenuInfo.cpp @@ -301,7 +301,8 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR NS_NewURI(getter_AddRefs(bgUri), bgStringValue); NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE); - nsCOMPtr il(do_CreateInstance("@mozilla.org/image/loader;1")); + nsCOMPtr il(do_GetService( + "@mozilla.org/image/loader;1")); NS_ENSURE_TRUE(il, NS_ERROR_FAILURE); return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr, diff --git a/image/build/nsImageModule.cpp b/image/build/nsImageModule.cpp index a78279e5155a..5eb42d753d3b 100644 --- a/image/build/nsImageModule.cpp +++ b/image/build/nsImageModule.cpp @@ -96,7 +96,7 @@ static nsresult imglib_Initialize() { mozilla::image::DiscardTracker::Initialize(); - imgLoader::GlobalInit(); + imgLoader::InitCache(); return NS_OK; } diff --git a/image/public/imgICache.idl b/image/public/imgICache.idl index c923cadaf40f..67e1166816ea 100644 --- a/image/public/imgICache.idl +++ b/image/public/imgICache.idl @@ -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(); }; diff --git a/image/public/imgITools.idl b/image/public/imgITools.idl index fb474ec620e6..147aac073c29 100644 --- a/image/public/imgITools.idl +++ b/image/public/imgITools.idl @@ -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 diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp index 2921dba21985..f51a666f0407 100644 --- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -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 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 request = new imgRequest(aLoader); - nsRefPtr entry = new imgCacheEntry(aLoader, request, aForcePrincipalCheckForCacheEntry); + nsRefPtr request = new imgRequest(); + nsRefPtr 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 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::Iterator it(mCacheTracker); it.Next(); ) + for (nsExpirationTracker::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 os = mozilla::services::GetObserverService(); + if (!os) + return NS_ERROR_FAILURE; + gCacheObserver = new imgCacheObserver(); NS_ADDREF(gCacheObserver); - nsCOMPtr 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 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 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 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 hvc = - new imgCacheValidator(progressproxy, this, request, aCX, forcePrincipalCheck); + new imgCacheValidator(progressproxy, request, aCX, forcePrincipalCheck); nsCOMPtr 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 channel = do_QueryInterface(aRequest); - if (channel) { - nsCOMPtr loadContext; - NS_QueryNotificationCallbacks(channel, loadContext); - isPrivate = loadContext && loadContext->UsePrivateBrowsing(); - } else if (aLoadGroup) { - nsCOMPtr callbacks; - aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); - if (callbacks) { - nsCOMPtr 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 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 loadContext; - NS_QueryNotificationCallbacks(channel, loadContext); - MOZ_ASSERT_IF(loadContext, loadContext->UsePrivateBrowsing() == mRespectPrivacy); -#endif - nsRefPtr request; nsCOMPtr 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 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--) { diff --git a/image/src/imgLoader.h b/image/src/imgLoader.h index 85756884eed2..64d3563b93ff 100644 --- a/image/src/imgLoader.h +++ b/image/src/imgLoader.h @@ -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 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 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 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__ diff --git a/image/src/imgRequest.cpp b/image/src/imgRequest.cpp index 2fc58a8e8702..e89e05a912f0 100644 --- a/image/src/imgRequest.cpp +++ b/image/src/imgRequest.cpp @@ -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; diff --git a/image/src/imgRequest.h b/image/src/imgRequest.h index 71c7715831cc..424631b5b8c1 100644 --- a/image/src/imgRequest.h +++ b/image/src/imgRequest.h @@ -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 mRequest; // The original URI we were loaded with. This is the same as the URI we are // keyed on in the cache. diff --git a/image/src/imgTools.cpp b/image/src/imgTools.cpp index eca1d366848e..827b46d0d64f 100644 --- a/image/src/imgTools.cpp +++ b/image/src/imgTools.cpp @@ -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 doc = do_QueryInterface(aDoc); - NS_IF_ADDREF(*aLoader = nsContentUtils::GetImgLoaderForDocument(doc)); - return NS_OK; -} - -NS_IMETHODIMP -imgTools::GetImgCacheForDocument(nsIDOMDocument* aDoc, imgICache** aCache) -{ - nsCOMPtr loader; - nsresult rv = GetImgLoaderForDocument(aDoc, getter_AddRefs(loader)); - NS_ENSURE_SUCCESS(rv, rv); - return CallQueryInterface(loader, aCache); -} diff --git a/image/test/mochitest/imgutils.js b/image/test/mochitest/imgutils.js index bbdcb9c4a46b..433518547296 100644 --- a/image/test/mochitest/imgutils.js +++ b/image/test/mochitest/imgutils.js @@ -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 } diff --git a/image/test/unit/async_load_tests.js b/image/test/unit/async_load_tests.js index f2346f79fb0d..0124701a06b9 100644 --- a/image/test/unit/async_load_tests.js +++ b/image/test/unit/async_load_tests.js @@ -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. diff --git a/image/test/unit/test_private_channel.js b/image/test/unit/test_private_channel.js deleted file mode 100644 index cc2f4fd939ba..000000000000 --- a/image/test/unit/test_private_channel.js +++ /dev/null @@ -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(); - }); - }); - }); - }); -} \ No newline at end of file diff --git a/image/test/unit/xpcshell.ini b/image/test/unit/xpcshell.ini index c9e710939048..b1086d4e6d75 100644 --- a/image/test/unit/xpcshell.ini +++ b/image/test/unit/xpcshell.ini @@ -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] \ No newline at end of file diff --git a/layout/build/nsContentDLF.cpp b/layout/build/nsContentDLF.cpp index 84dd80f6fa36..011e29963351 100644 --- a/layout/build/nsContentDLF.cpp +++ b/layout/build/nsContentDLF.cpp @@ -481,7 +481,7 @@ nsContentDLF::CreateXULDocument(const char* aCommand, } bool nsContentDLF::IsImageContentType(const char* aContentType) { - nsCOMPtr loader(do_CreateInstance("@mozilla.org/image/loader;1")); + nsCOMPtr loader(do_GetService("@mozilla.org/image/loader;1")); bool isDecoderAvailable = false; loader->SupportImageWithMimeType(aContentType, &isDecoderAvailable); return isDecoderAvailable; diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 6dfde2a2a9ee..748107df0e45 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1786,8 +1786,8 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, nsCOMPtr realURI; SpecToURI(aSpec, sIOService, getter_AddRefs(realURI)); - nsCOMPtr il = - nsContentUtils::GetImgLoaderForDocument(aPresContext->Document()); + nsCOMPtr il(do_GetService("@mozilla.org/image/loader;1", &rv)); + if (NS_FAILED(rv)) return rv; nsCOMPtr loadGroup; GetLoadGroup(aPresContext, getter_AddRefs(loadGroup)); diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm index 4252f18c0b56..e0c07c4a7c19 100644 --- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -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 loadGroup = document->GetDocumentLoadGroup(); if (!loadGroup) return NS_ERROR_FAILURE; - nsCOMPtr loader = nsContentUtils::GetImgLoaderForDocument(document); - if (!loader) return NS_ERROR_FAILURE; + nsresult rv = NS_ERROR_FAILURE; + nsCOMPtr 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).