mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 867755 - Support OnDataAvailable and OnStopRequest off main thread for image loading r=seth
This commit is contained in:
parent
6f48aab55b
commit
1b740124a5
@ -7,6 +7,7 @@
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsMimeTypes.h"
|
||||
|
||||
#include "ImageFactory.h"
|
||||
#include "RasterImage.h"
|
||||
|
||||
#include "imgLoader.h"
|
||||
@ -81,6 +82,7 @@ static nsresult
|
||||
imglib_Initialize()
|
||||
{
|
||||
mozilla::image::DiscardTracker::Initialize();
|
||||
mozilla::image::ImageFactory::Initialize();
|
||||
mozilla::image::RasterImage::Initialize();
|
||||
imgLoader::GlobalInit();
|
||||
return NS_OK;
|
||||
|
@ -10,15 +10,10 @@
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
#ifdef DEBUG_imagelib
|
||||
static const bool allowOMTURIAccess = true;
|
||||
#else
|
||||
static const bool allowOMTURIAccess = false;
|
||||
#endif
|
||||
|
||||
// Constructor
|
||||
ImageResource::ImageResource(imgStatusTracker* aStatusTracker, nsIURI* aURI) :
|
||||
mURI(new nsMainThreadPtrHolder<nsIURI>(aURI, allowOMTURIAccess)),
|
||||
ImageResource::ImageResource(imgStatusTracker* aStatusTracker,
|
||||
ImageURL* aURI) :
|
||||
mURI(aURI),
|
||||
mInnerWindowId(0),
|
||||
mAnimationConsumers(0),
|
||||
mAnimationMode(kNormalAnimMode),
|
||||
|
@ -9,8 +9,7 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "imgStatusTracker.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsProxyRelease.h" // for nsMainThreadPtrHolder and nsMainThreadPtrHandle
|
||||
#include "ImageURL.h"
|
||||
|
||||
class nsIRequest;
|
||||
class nsIInputStream;
|
||||
@ -132,7 +131,7 @@ public:
|
||||
virtual bool HasError() = 0;
|
||||
virtual void SetHasError() = 0;
|
||||
|
||||
virtual nsIURI* GetURI() = 0;
|
||||
virtual ImageURL* GetURI() = 0;
|
||||
};
|
||||
|
||||
class ImageResource : public Image
|
||||
@ -159,10 +158,11 @@ public:
|
||||
* Returns a non-AddRefed pointer to the URI associated with this image.
|
||||
* Illegal to use off-main-thread.
|
||||
*/
|
||||
virtual nsIURI* GetURI() MOZ_OVERRIDE { return mURI.get(); }
|
||||
virtual ImageURL* GetURI() MOZ_OVERRIDE { return mURI.get(); }
|
||||
|
||||
protected:
|
||||
ImageResource(imgStatusTracker* aStatusTracker, nsIURI* aURI);
|
||||
ImageResource(imgStatusTracker* aStatusTracker,
|
||||
ImageURL* aURI);
|
||||
|
||||
// Shared functionality for implementors of imgIContainer. Every
|
||||
// implementation of attribute animationMode should forward here.
|
||||
@ -188,7 +188,7 @@ protected:
|
||||
|
||||
// Member data shared by all implementations of this abstract class
|
||||
nsRefPtr<imgStatusTracker> mStatusTracker;
|
||||
nsMainThreadPtrHandle<nsIURI> mURI;
|
||||
nsRefPtr<ImageURL> mURI;
|
||||
uint64_t mInnerWindowId;
|
||||
uint32_t mAnimationConsumers;
|
||||
uint16_t mAnimationMode; // Enum values in imgIContainer
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIRequest.h"
|
||||
|
||||
#include "RasterImage.h"
|
||||
@ -31,16 +30,19 @@ static bool gInitializedPrefCaches = false;
|
||||
static bool gDecodeOnDraw = false;
|
||||
static bool gDiscardable = false;
|
||||
|
||||
static void
|
||||
InitPrefCaches()
|
||||
/*static*/ void
|
||||
ImageFactory::Initialize()
|
||||
{
|
||||
Preferences::AddBoolVarCache(&gDiscardable, "image.mem.discardable");
|
||||
Preferences::AddBoolVarCache(&gDecodeOnDraw, "image.mem.decodeondraw");
|
||||
gInitializedPrefCaches = true;
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!gInitializedPrefCaches) {
|
||||
Preferences::AddBoolVarCache(&gDiscardable, "image.mem.discardable");
|
||||
Preferences::AddBoolVarCache(&gDecodeOnDraw, "image.mem.decodeondraw");
|
||||
gInitializedPrefCaches = true;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ComputeImageFlags(nsIURI* uri, bool isMultiPart)
|
||||
ComputeImageFlags(ImageURL* uri, bool isMultiPart)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
@ -83,13 +85,12 @@ ComputeImageFlags(nsIURI* uri, bool isMultiPart)
|
||||
ImageFactory::CreateImage(nsIRequest* aRequest,
|
||||
imgStatusTracker* aStatusTracker,
|
||||
const nsCString& aMimeType,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
bool aIsMultiPart,
|
||||
uint32_t aInnerWindowId)
|
||||
{
|
||||
// Register our pref observers if we haven't yet.
|
||||
if (MOZ_UNLIKELY(!gInitializedPrefCaches))
|
||||
InitPrefCaches();
|
||||
MOZ_ASSERT(gInitializedPrefCaches,
|
||||
"Pref observers should have been initialized already");
|
||||
|
||||
// Compute the image's initialization flags.
|
||||
uint32_t imageFlags = ComputeImageFlags(aURI, aIsMultiPart);
|
||||
@ -175,7 +176,7 @@ GetContentSize(nsIRequest* aRequest)
|
||||
ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
||||
imgStatusTracker* aStatusTracker,
|
||||
const nsCString& aMimeType,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
uint32_t aImageFlags,
|
||||
uint32_t aInnerWindowId)
|
||||
{
|
||||
@ -206,7 +207,9 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::net::nsMediaFragmentURIParser parser(aURI);
|
||||
nsAutoCString ref;
|
||||
aURI->GetRef(ref);
|
||||
mozilla::net::nsMediaFragmentURIParser parser(ref);
|
||||
if (parser.HasResolution()) {
|
||||
newImage->SetRequestedResolution(parser.GetResolution());
|
||||
}
|
||||
@ -218,7 +221,7 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
|
||||
ImageFactory::CreateVectorImage(nsIRequest* aRequest,
|
||||
imgStatusTracker* aStatusTracker,
|
||||
const nsCString& aMimeType,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
uint32_t aImageFlags,
|
||||
uint32_t aInnerWindowId)
|
||||
{
|
||||
|
@ -8,22 +8,29 @@
|
||||
#define MOZILLA_IMAGELIB_IMAGEFACTORY_H_
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
class nsCString;
|
||||
class nsIRequest;
|
||||
class nsIURI;
|
||||
class imgStatusTracker;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
class Image;
|
||||
class ImageURL;
|
||||
|
||||
class ImageFactory
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Registers vars with Preferences. Should only be called on the main thread.
|
||||
*/
|
||||
static void Initialize();
|
||||
|
||||
/**
|
||||
* Creates a new image with the given properties.
|
||||
* Can be called on or off the main thread.
|
||||
*
|
||||
* @param aRequest The associated request.
|
||||
* @param aStatusTracker A status tracker for the image to use.
|
||||
@ -35,7 +42,7 @@ public:
|
||||
static already_AddRefed<Image> CreateImage(nsIRequest* aRequest,
|
||||
imgStatusTracker* aStatusTracker,
|
||||
const nsCString& aMimeType,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
bool aIsMultiPart,
|
||||
uint32_t aInnerWindowId);
|
||||
/**
|
||||
@ -51,14 +58,14 @@ private:
|
||||
static already_AddRefed<Image> CreateRasterImage(nsIRequest* aRequest,
|
||||
imgStatusTracker* aStatusTracker,
|
||||
const nsCString& aMimeType,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
uint32_t aImageFlags,
|
||||
uint32_t aInnerWindowId);
|
||||
|
||||
static already_AddRefed<Image> CreateVectorImage(nsIRequest* aRequest,
|
||||
imgStatusTracker* aStatusTracker,
|
||||
const nsCString& aMimeType,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
uint32_t aImageFlags,
|
||||
uint32_t aInnerWindowId);
|
||||
|
||||
|
86
image/src/ImageURL.h
Normal file
86
image/src/ImageURL.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_IMAGELIB_IMAGEURL_H_
|
||||
#define MOZILLA_IMAGELIB_IMAGEURL_H_
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
/** ImageURL
|
||||
*
|
||||
* nsStandardURL is not threadsafe, so this class is created to hold only the
|
||||
* necessary URL data required for image loading and decoding.
|
||||
*
|
||||
* Note: Although several APIs have the same or similar prototypes as those
|
||||
* found in nsIURI/nsStandardURL, the class does not implement nsIURI. This is
|
||||
* intentional; functionality is limited, and is only useful for imagelib code.
|
||||
* By not implementing nsIURI, external code cannot unintentionally be given an
|
||||
* nsIURI pointer with this limited class behind it; instead, conversion to a
|
||||
* fully implemented nsIURI is required (e.g. through NS_NewURI).
|
||||
*/
|
||||
class ImageURL
|
||||
{
|
||||
public:
|
||||
explicit ImageURL(nsIURI* aURI) {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
|
||||
aURI->GetSpec(mSpec);
|
||||
aURI->GetScheme(mScheme);
|
||||
aURI->GetRef(mRef);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::image::ImageURL)
|
||||
|
||||
nsresult GetSpec(nsACString &result) {
|
||||
result = mSpec;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetScheme(nsACString &result) {
|
||||
result = mScheme;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SchemeIs(const char *scheme, bool *result)
|
||||
{
|
||||
NS_PRECONDITION(scheme, "scheme is null");
|
||||
NS_PRECONDITION(result, "result is null");
|
||||
|
||||
*result = mScheme.Equals(scheme);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetRef(nsACString &result) {
|
||||
result = mRef;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI> ToIURI() {
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Convert to nsIURI on main thread only; it is not threadsafe.");
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
NS_NewURI(getter_AddRefs(newURI), mSpec);
|
||||
return newURI.forget();
|
||||
}
|
||||
|
||||
private:
|
||||
// Since this is a basic storage class, no duplication of spec parsing is
|
||||
// included in the functionality. Instead, the class depends upon the
|
||||
// parsing implementation in the nsIURI class used in object construction.
|
||||
// This means each field is stored separately, but since only a few are
|
||||
// required, this small memory tradeoff for threadsafe usage should be ok.
|
||||
nsAutoCString mSpec;
|
||||
nsAutoCString mScheme;
|
||||
nsAutoCString mRef;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_IMAGELIB_IMAGEURL_H_
|
@ -134,7 +134,7 @@ ImageWrapper::SetHasError()
|
||||
mInnerImage->SetHasError();
|
||||
}
|
||||
|
||||
nsIURI*
|
||||
ImageURL*
|
||||
ImageWrapper::GetURI()
|
||||
{
|
||||
return mInnerImage->GetURI();
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
virtual bool HasError() MOZ_OVERRIDE;
|
||||
virtual void SetHasError() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsIURI* GetURI() MOZ_OVERRIDE;
|
||||
virtual ImageURL* GetURI() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
ImageWrapper(Image* aInnerImage)
|
||||
|
@ -375,7 +375,7 @@ NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
|
||||
|
||||
//******************************************************************************
|
||||
RasterImage::RasterImage(imgStatusTracker* aStatusTracker,
|
||||
nsIURI* aURI /* = nullptr */) :
|
||||
ImageURL* aURI /* = nullptr */) :
|
||||
ImageResource(aStatusTracker, aURI), // invoke superclass's constructor
|
||||
mSize(0,0),
|
||||
mFrameDecodeFlags(DECODE_FLAGS_DEFAULT),
|
||||
@ -2188,6 +2188,10 @@ RasterImage::RequestDecode()
|
||||
NS_IMETHODIMP
|
||||
RasterImage::StartDecoding()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethod(this, &RasterImage::StartDecoding));
|
||||
}
|
||||
// Here we are explicitly trading off flashing for responsiveness in the case
|
||||
// that we're redecoding an image (see bug 845147).
|
||||
return RequestDecodeCore(mHasBeenDecoded ?
|
||||
@ -3040,6 +3044,13 @@ RasterImage::DecodePool::Singleton()
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIEventTarget>
|
||||
RasterImage::DecodePool::GetEventTarget()
|
||||
{
|
||||
nsCOMPtr<nsIEventTarget> target = do_QueryInterface(mThreadPool);
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
RasterImage::DecodePool::DecodePool()
|
||||
: mThreadPoolMutex("Thread Pool")
|
||||
{
|
||||
|
@ -246,6 +246,10 @@ public:
|
||||
bool aLastPart) MOZ_OVERRIDE;
|
||||
virtual nsresult OnNewSourceData() MOZ_OVERRIDE;
|
||||
|
||||
static already_AddRefed<nsIEventTarget> GetEventTarget() {
|
||||
return DecodePool::Singleton()->GetEventTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* A hint of the number of bytes of source data that the image contains. If
|
||||
* called early on, this can help reduce copying and reallocations by
|
||||
@ -414,6 +418,14 @@ private:
|
||||
*/
|
||||
nsresult DecodeUntilSizeAvailable(RasterImage* aImg);
|
||||
|
||||
/**
|
||||
* Returns an event target interface to the thread pool; primarily for
|
||||
* OnDataAvailable delivery off main thread.
|
||||
*
|
||||
* @return An nsIEventTarget interface to mThreadPool.
|
||||
*/
|
||||
already_AddRefed<nsIEventTarget> GetEventTarget();
|
||||
|
||||
virtual ~DecodePool();
|
||||
|
||||
private: /* statics */
|
||||
@ -732,7 +744,8 @@ private: // data
|
||||
bool StoringSourceData() const;
|
||||
|
||||
protected:
|
||||
RasterImage(imgStatusTracker* aStatusTracker = nullptr, nsIURI* aURI = nullptr);
|
||||
RasterImage(imgStatusTracker* aStatusTracker = nullptr,
|
||||
ImageURL* aURI = nullptr);
|
||||
|
||||
bool ShouldAnimate();
|
||||
|
||||
|
@ -302,7 +302,7 @@ NS_IMPL_ISUPPORTS3(VectorImage,
|
||||
// Constructor / Destructor
|
||||
|
||||
VectorImage::VectorImage(imgStatusTracker* aStatusTracker,
|
||||
nsIURI* aURI /* = nullptr */) :
|
||||
ImageURL* aURI /* = nullptr */) :
|
||||
ImageResource(aStatusTracker, aURI), // invoke superclass's constructor
|
||||
mIsInitialized(false),
|
||||
mIsFullyLoaded(false),
|
||||
|
@ -75,7 +75,8 @@ public:
|
||||
void OnSVGDocumentError();
|
||||
|
||||
protected:
|
||||
VectorImage(imgStatusTracker* aStatusTracker = nullptr, nsIURI* aURI = nullptr);
|
||||
VectorImage(imgStatusTracker* aStatusTracker = nullptr,
|
||||
ImageURL* aURI = nullptr);
|
||||
|
||||
virtual nsresult StartAnimation();
|
||||
virtual nsresult StopAnimation();
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
#include "ImageLogging.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "imgLoader.h"
|
||||
#include "imgRequestProxy.h"
|
||||
|
||||
@ -514,7 +515,7 @@ void imgCacheEntry::UpdateCache(int32_t diff /* = 0 */)
|
||||
// Don't update the cache if we've been removed from it or it doesn't care
|
||||
// about our size or usage.
|
||||
if (!Evicted() && HasNoProxies()) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsRefPtr<ImageURL> uri;
|
||||
mRequest->GetURI(getter_AddRefs(uri));
|
||||
mLoader->CacheEntriesChanged(uri, diff);
|
||||
}
|
||||
@ -523,7 +524,7 @@ void imgCacheEntry::UpdateCache(int32_t diff /* = 0 */)
|
||||
void imgCacheEntry::SetHasNoProxies(bool hasNoProxies)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsRefPtr<ImageURL> uri;
|
||||
mRequest->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString spec;
|
||||
if (uri)
|
||||
@ -647,7 +648,7 @@ nsresult imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup
|
||||
*/
|
||||
proxyRequest->SetLoadFlags(aLoadFlags);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsRefPtr<ImageURL> uri;
|
||||
aRequest->GetURI(getter_AddRefs(uri));
|
||||
|
||||
// init adds itself to imgRequest's list of observers
|
||||
@ -705,7 +706,7 @@ void imgCacheExpirationTracker::NotifyExpired(imgCacheEntry *entry)
|
||||
#if defined(PR_LOGGING)
|
||||
nsRefPtr<imgRequest> req(entry->GetRequest());
|
||||
if (req) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsRefPtr<ImageURL> uri;
|
||||
req->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
@ -776,22 +777,33 @@ void imgLoader::VerifyCacheSizes()
|
||||
|
||||
imgLoader::imgCacheTable & imgLoader::GetCache(nsIURI *aURI)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
|
||||
bool chrome = false;
|
||||
aURI->SchemeIs("chrome", &chrome);
|
||||
if (chrome)
|
||||
return mChromeCache;
|
||||
else
|
||||
return mCache;
|
||||
return chrome ? mChromeCache : mCache;
|
||||
}
|
||||
|
||||
imgCacheQueue & imgLoader::GetCacheQueue(nsIURI *aURI)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
|
||||
bool chrome = false;
|
||||
aURI->SchemeIs("chrome", &chrome);
|
||||
if (chrome)
|
||||
return mChromeCacheQueue;
|
||||
else
|
||||
return mCacheQueue;
|
||||
return chrome ? mChromeCacheQueue : mCacheQueue;
|
||||
|
||||
}
|
||||
|
||||
imgLoader::imgCacheTable & imgLoader::GetCache(ImageURL *aURI)
|
||||
{
|
||||
bool chrome = false;
|
||||
aURI->SchemeIs("chrome", &chrome);
|
||||
return chrome ? mChromeCache : mCache;
|
||||
}
|
||||
|
||||
imgCacheQueue & imgLoader::GetCacheQueue(ImageURL *aURI)
|
||||
{
|
||||
bool chrome = false;
|
||||
aURI->SchemeIs("chrome", &chrome);
|
||||
return chrome ? mChromeCacheQueue : mCacheQueue;
|
||||
}
|
||||
|
||||
void imgLoader::GlobalInit()
|
||||
@ -1018,7 +1030,7 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
|
||||
bool imgLoader::SetHasNoProxies(ImageURL *key, imgCacheEntry *entry)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
nsAutoCString spec;
|
||||
@ -1048,7 +1060,7 @@ bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool imgLoader::SetHasProxies(nsIURI *key)
|
||||
bool imgLoader::SetHasProxies(ImageURL *key)
|
||||
{
|
||||
VerifyCacheSizes();
|
||||
|
||||
@ -1075,7 +1087,7 @@ bool imgLoader::SetHasProxies(nsIURI *key)
|
||||
return false;
|
||||
}
|
||||
|
||||
void imgLoader::CacheEntriesChanged(nsIURI *uri, int32_t sizediff /* = 0 */)
|
||||
void imgLoader::CacheEntriesChanged(ImageURL *uri, int32_t sizediff /* = 0 */)
|
||||
{
|
||||
imgCacheQueue &queue = GetCacheQueue(uri);
|
||||
queue.MarkDirty();
|
||||
@ -1098,7 +1110,7 @@ void imgLoader::CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue)
|
||||
#if defined(PR_LOGGING)
|
||||
nsRefPtr<imgRequest> req(entry->GetRequest());
|
||||
if (req) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsRefPtr<ImageURL> uri;
|
||||
req->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
@ -1190,7 +1202,10 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
|
||||
nsRefPtr<imgCacheValidator> hvc =
|
||||
new imgCacheValidator(progressproxy, this, request, aCX, forcePrincipalCheck);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener = hvc.get();
|
||||
// Casting needed here to get past multiple inheritance.
|
||||
nsCOMPtr<nsIStreamListener> listener =
|
||||
do_QueryInterface(static_cast<nsIThreadRetargetableStreamListener*>(hvc));
|
||||
NS_ENSURE_TRUE(listener, false);
|
||||
|
||||
// We must set the notification callbacks before setting up the
|
||||
// CORS listener, because that's also interested inthe
|
||||
@ -1200,7 +1215,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
|
||||
if (aCORSMode != imgIRequest::CORS_NONE) {
|
||||
bool withCredentials = aCORSMode == imgIRequest::CORS_USE_CREDENTIALS;
|
||||
nsRefPtr<nsCORSListenerProxy> corsproxy =
|
||||
new nsCORSListenerProxy(hvc, aLoadingPrincipal, withCredentials);
|
||||
new nsCORSListenerProxy(listener, aLoadingPrincipal, withCredentials);
|
||||
rv = corsproxy->Init(newChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
@ -1353,8 +1368,22 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry,
|
||||
return !validateRequest;
|
||||
}
|
||||
|
||||
|
||||
bool imgLoader::RemoveFromCache(nsIURI *aKey)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
|
||||
|
||||
if (!aKey) return false;
|
||||
|
||||
imgCacheTable &cache = GetCache(aKey);
|
||||
imgCacheQueue &queue = GetCacheQueue(aKey);
|
||||
|
||||
nsAutoCString spec;
|
||||
aKey->GetSpec(spec);
|
||||
|
||||
return RemoveFromCache(spec, cache, queue);
|
||||
}
|
||||
|
||||
bool imgLoader::RemoveFromCache(ImageURL *aKey)
|
||||
{
|
||||
if (!aKey) return false;
|
||||
|
||||
@ -1364,6 +1393,13 @@ bool imgLoader::RemoveFromCache(nsIURI *aKey)
|
||||
nsAutoCString spec;
|
||||
aKey->GetSpec(spec);
|
||||
|
||||
return RemoveFromCache(spec, cache, queue);
|
||||
}
|
||||
|
||||
bool imgLoader::RemoveFromCache(nsCString& spec,
|
||||
imgCacheTable &cache,
|
||||
imgCacheQueue &queue)
|
||||
{
|
||||
LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::RemoveFromCache", "uri", spec.get());
|
||||
|
||||
nsRefPtr<imgCacheEntry> entry;
|
||||
@ -1396,7 +1432,7 @@ bool imgLoader::RemoveFromCache(imgCacheEntry *entry)
|
||||
|
||||
nsRefPtr<imgRequest> request = entry->GetRequest();
|
||||
if (request) {
|
||||
nsCOMPtr<nsIURI> key;
|
||||
nsRefPtr<ImageURL> key;
|
||||
if (NS_SUCCEEDED(request->GetURI(getter_AddRefs(key))) && key) {
|
||||
imgCacheTable &cache = GetCache(key);
|
||||
imgCacheQueue &queue = GetCacheQueue(key);
|
||||
@ -2001,7 +2037,10 @@ nsresult imgLoader::GetMimeTypeFromContent(const char* aContents, uint32_t aLeng
|
||||
#include "nsIRequest.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS2(ProxyListener, nsIStreamListener, nsIRequestObserver)
|
||||
NS_IMPL_ISUPPORTS3(ProxyListener,
|
||||
nsIStreamListener,
|
||||
nsIThreadRetargetableStreamListener,
|
||||
nsIRequestObserver)
|
||||
|
||||
ProxyListener::ProxyListener(nsIStreamListener *dest) :
|
||||
mDestListener(dest)
|
||||
@ -2078,11 +2117,30 @@ ProxyListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
|
||||
return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count);
|
||||
}
|
||||
|
||||
/** nsThreadRetargetableStreamListener methods **/
|
||||
NS_IMETHODIMP
|
||||
ProxyListener::CheckListenerChain()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!");
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
|
||||
do_QueryInterface(mDestListener, &rv);
|
||||
if (retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
}
|
||||
PR_LOG(GetImgLog(), PR_LOG_DEBUG,
|
||||
("ProxyListener::CheckListenerChain %s [this=%p listener=%p rv=%x]",
|
||||
(NS_SUCCEEDED(rv) ? "success" : "failure"),
|
||||
this, (nsIStreamListener*)mDestListener, rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* http validate class. check a channel for a 304
|
||||
*/
|
||||
|
||||
NS_IMPL_ISUPPORTS5(imgCacheValidator, nsIStreamListener, nsIRequestObserver,
|
||||
NS_IMPL_ISUPPORTS6(imgCacheValidator, nsIStreamListener, nsIRequestObserver,
|
||||
nsIThreadRetargetableStreamListener,
|
||||
nsIChannelEventSink, nsIInterfaceRequestor,
|
||||
nsIAsyncVerifyRedirectCallback)
|
||||
|
||||
@ -2169,7 +2227,11 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
|
||||
// We can't load out of cache. We have to create a whole new request for the
|
||||
// data that's coming in off the channel.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mRequest->GetURI(getter_AddRefs(uri));
|
||||
{
|
||||
nsRefPtr<ImageURL> imageURL;
|
||||
mRequest->GetURI(getter_AddRefs(imageURL));
|
||||
uri = imageURL->ToIURI();
|
||||
}
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
nsAutoCString spec;
|
||||
@ -2245,6 +2307,24 @@ imgCacheValidator::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
|
||||
return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count);
|
||||
}
|
||||
|
||||
/** nsIThreadRetargetableStreamListener methods **/
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgCacheValidator::CheckListenerChain()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!");
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
|
||||
do_QueryInterface(mDestListener, &rv);
|
||||
if (retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
}
|
||||
PR_LOG(GetImgLog(), PR_LOG_DEBUG,
|
||||
("[this=%p] imgCacheValidator::CheckListenerChain -- rv %d=%s",
|
||||
this, NS_SUCCEEDED(rv) ? "succeeded" : "failed", rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** nsIInterfaceRequestor methods **/
|
||||
|
||||
NS_IMETHODIMP imgCacheValidator::GetInterface(const nsIID & aIID, void **aResult)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "imgRequest.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "imgIRequest.h"
|
||||
|
||||
class imgLoader;
|
||||
@ -29,6 +30,12 @@ class imgCacheExpirationTracker;
|
||||
class imgMemoryReporter;
|
||||
class nsIChannelPolicy;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
class ImageURL;
|
||||
}
|
||||
}
|
||||
|
||||
class imgCacheEntry
|
||||
{
|
||||
public:
|
||||
@ -205,6 +212,9 @@ class imgLoader : public imgILoader,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
typedef mozilla::image::ImageURL ImageURL;
|
||||
typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IMGILOADER
|
||||
NS_DECL_NSICONTENTSNIFFER
|
||||
@ -263,6 +273,10 @@ public:
|
||||
nsresult InitCache();
|
||||
|
||||
bool RemoveFromCache(nsIURI *aKey);
|
||||
bool RemoveFromCache(ImageURL *aKey);
|
||||
bool RemoveFromCache(nsCString &spec,
|
||||
imgCacheTable &cache,
|
||||
imgCacheQueue &queue);
|
||||
bool RemoveFromCache(imgCacheEntry *entry);
|
||||
|
||||
bool PutIntoCache(nsIURI *key, imgCacheEntry *entry);
|
||||
@ -304,8 +318,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);
|
||||
bool SetHasNoProxies(ImageURL *key, imgCacheEntry *entry);
|
||||
bool SetHasProxies(ImageURL *key);
|
||||
|
||||
private: // methods
|
||||
|
||||
@ -336,15 +350,14 @@ private: // methods
|
||||
|
||||
void ReadAcceptHeaderPref();
|
||||
|
||||
|
||||
typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
|
||||
|
||||
nsresult EvictEntries(imgCacheTable &aCacheToClear);
|
||||
nsresult EvictEntries(imgCacheQueue &aQueueToClear);
|
||||
|
||||
imgCacheTable &GetCache(nsIURI *aURI);
|
||||
imgCacheQueue &GetCacheQueue(nsIURI *aURI);
|
||||
void CacheEntriesChanged(nsIURI *aURI, int32_t sizediff = 0);
|
||||
imgCacheTable &GetCache(ImageURL *aURI);
|
||||
imgCacheQueue &GetCacheQueue(ImageURL *aURI);
|
||||
void CacheEntriesChanged(ImageURL *aURI, int32_t sizediff = 0);
|
||||
void CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue);
|
||||
|
||||
private: // data
|
||||
@ -375,8 +388,10 @@ private: // data
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
|
||||
class ProxyListener : public nsIStreamListener
|
||||
, public nsIThreadRetargetableStreamListener
|
||||
{
|
||||
public:
|
||||
ProxyListener(nsIStreamListener *dest);
|
||||
@ -385,6 +400,7 @@ public:
|
||||
/* additional members */
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
private:
|
||||
@ -427,6 +443,7 @@ class nsProgressNotificationProxy MOZ_FINAL
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class imgCacheValidator : public nsIStreamListener,
|
||||
public nsIThreadRetargetableStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
@ -439,6 +456,7 @@ public:
|
||||
void AddProxy(imgRequestProxy *aProxy);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
@ -12,9 +12,11 @@
|
||||
#include "imgStatusTracker.h"
|
||||
#include "ImageFactory.h"
|
||||
#include "Image.h"
|
||||
#include "RasterImage.h"
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIMultiPartChannel.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
@ -47,8 +49,9 @@ GetImgLog()
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMPL_ISUPPORTS5(imgRequest,
|
||||
NS_IMPL_ISUPPORTS6(imgRequest,
|
||||
nsIStreamListener, nsIRequestObserver,
|
||||
nsIThreadRetargetableStreamListener,
|
||||
nsIChannelEventSink,
|
||||
nsIInterfaceRequestor,
|
||||
nsIAsyncVerifyRedirectCallback)
|
||||
@ -85,6 +88,8 @@ nsresult imgRequest::Init(nsIURI *aURI,
|
||||
nsIPrincipal* aLoadingPrincipal,
|
||||
int32_t aCORSMode)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
|
||||
|
||||
LOG_FUNC(GetImgLog(), "imgRequest::Init");
|
||||
|
||||
NS_ABORT_IF_FALSE(!mImage, "Multiple calls to init");
|
||||
@ -95,7 +100,8 @@ nsresult imgRequest::Init(nsIURI *aURI,
|
||||
|
||||
mProperties = do_CreateInstance("@mozilla.org/properties;1");
|
||||
|
||||
mURI = aURI;
|
||||
// Use ImageURL to ensure access to URI data off main thread.
|
||||
mURI = new ImageURL(aURI);
|
||||
mCurrentURI = aCurrentURI;
|
||||
mRequest = aRequest;
|
||||
mChannel = aChannel;
|
||||
@ -248,14 +254,21 @@ void imgRequest::Cancel(nsresult aStatus)
|
||||
|
||||
statusTracker.RecordCancel();
|
||||
|
||||
RemoveFromCache();
|
||||
if (NS_IsMainThread()) {
|
||||
RemoveFromCache();
|
||||
} else {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethod(this, &imgRequest::RemoveFromCache));
|
||||
}
|
||||
|
||||
if (mRequest && statusTracker.IsLoading())
|
||||
mRequest->Cancel(aStatus);
|
||||
}
|
||||
|
||||
nsresult imgRequest::GetURI(nsIURI **aURI)
|
||||
nsresult imgRequest::GetURI(ImageURL **aURI)
|
||||
{
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
LOG_FUNC(GetImgLog(), "imgRequest::GetURI");
|
||||
|
||||
if (mURI) {
|
||||
@ -570,6 +583,26 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
|
||||
this->Cancel(NS_IMAGELIB_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Try to retarget OnDataAvailable to a decode thread.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
|
||||
nsCOMPtr<nsIThreadRetargetableRequest> retargetable =
|
||||
do_QueryInterface(aRequest);
|
||||
if (httpChannel && retargetable &&
|
||||
!(mIsMultiPartChannel && mImage)) {
|
||||
nsAutoCString mimeType;
|
||||
nsresult rv = httpChannel->GetContentType(mimeType);
|
||||
if (NS_SUCCEEDED(rv) && !mimeType.EqualsLiteral(IMAGE_SVG_XML)) {
|
||||
// Image object not created until OnDataAvailable, so forward to static
|
||||
// DecodePool directly.
|
||||
nsCOMPtr<nsIEventTarget> target = RasterImage::GetEventTarget();
|
||||
rv = retargetable->RetargetDeliveryTo(target);
|
||||
}
|
||||
PR_LOG(GetImgLog(), PR_LOG_WARNING,
|
||||
("[this=%p] imgRequest::OnStartRequest -- "
|
||||
"RetargetDeliveryTo rv %d=%s\n",
|
||||
this, NS_SUCCEEDED(rv) ? "succeeded" : "failed", rv));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -644,6 +677,15 @@ struct mimetype_closure
|
||||
static NS_METHOD sniff_mimetype_callback(nsIInputStream* in, void* closure, const char* fromRawSegment,
|
||||
uint32_t toOffset, uint32_t count, uint32_t *writeCount);
|
||||
|
||||
/** nsThreadRetargetableStreamListener methods **/
|
||||
NS_IMETHODIMP
|
||||
imgRequest::CheckListenerChain()
|
||||
{
|
||||
// TODO Might need more checking here.
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** nsIStreamListener methods **/
|
||||
|
||||
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long long sourceOffset, in unsigned long count); */
|
||||
@ -720,28 +762,14 @@ imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
|
||||
mStatusTracker = freshTracker;
|
||||
}
|
||||
|
||||
/* set our mimetype as a property */
|
||||
nsCOMPtr<nsISupportsCString> contentType(do_CreateInstance("@mozilla.org/supports-cstring;1"));
|
||||
if (contentType) {
|
||||
contentType->SetData(mContentType);
|
||||
mProperties->Set("type", contentType);
|
||||
}
|
||||
|
||||
/* set our content disposition as a property */
|
||||
nsAutoCString disposition;
|
||||
if (chan) {
|
||||
chan->GetContentDispositionHeader(disposition);
|
||||
}
|
||||
if (!disposition.IsEmpty()) {
|
||||
nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1"));
|
||||
if (contentDisposition) {
|
||||
contentDisposition->SetData(disposition);
|
||||
mProperties->Set("content-disposition", contentDisposition);
|
||||
}
|
||||
}
|
||||
SetProperties(chan);
|
||||
|
||||
LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnDataAvailable", "content type", mContentType.get());
|
||||
|
||||
// XXX If server lied about mimetype and it's SVG, we may need to copy
|
||||
// the data and dispatch back to the main thread, AND tell the channel to
|
||||
// dispatch there in the future.
|
||||
|
||||
// Now we can create a new image to hold the data. If we don't have a decoder
|
||||
// for this mimetype we'll find out about it here.
|
||||
mImage = ImageFactory::CreateImage(aRequest, mStatusTracker, mContentType,
|
||||
@ -785,6 +813,58 @@ imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class SetPropertiesEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
SetPropertiesEvent(imgRequest* aImgRequest, nsIChannel* aChan)
|
||||
: mImgRequest(aImgRequest)
|
||||
, mChan(aChan)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread(), "Should be created off the main thread");
|
||||
MOZ_ASSERT(aImgRequest, "aImgRequest cannot be null");
|
||||
}
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should run on the main thread only");
|
||||
MOZ_ASSERT(mImgRequest, "mImgRequest cannot be null");
|
||||
mImgRequest->SetProperties(mChan);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<imgRequest> mImgRequest;
|
||||
nsCOMPtr<nsIChannel> mChan;
|
||||
};
|
||||
|
||||
void
|
||||
imgRequest::SetProperties(nsIChannel* aChan)
|
||||
{
|
||||
// Force execution on main thread since some property objects are non
|
||||
// threadsafe.
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(new SetPropertiesEvent(this, aChan));
|
||||
return;
|
||||
}
|
||||
/* set our mimetype as a property */
|
||||
nsCOMPtr<nsISupportsCString> contentType(do_CreateInstance("@mozilla.org/supports-cstring;1"));
|
||||
if (contentType) {
|
||||
contentType->SetData(mContentType);
|
||||
mProperties->Set("type", contentType);
|
||||
}
|
||||
|
||||
/* set our content disposition as a property */
|
||||
nsAutoCString disposition;
|
||||
if (aChan) {
|
||||
aChan->GetContentDispositionHeader(disposition);
|
||||
}
|
||||
if (!disposition.IsEmpty()) {
|
||||
nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1"));
|
||||
if (contentDisposition) {
|
||||
contentDisposition->SetData(disposition);
|
||||
mProperties->Set("content-disposition", contentDisposition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NS_METHOD sniff_mimetype_callback(nsIInputStream* in,
|
||||
void* data,
|
||||
const char* fromRawSegment,
|
||||
|
@ -10,10 +10,12 @@
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
@ -34,19 +36,22 @@ class nsIURI;
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
class Image;
|
||||
class ImageURL;
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
class imgRequest : public nsIStreamListener,
|
||||
public nsIThreadRetargetableStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIAsyncVerifyRedirectCallback
|
||||
{
|
||||
public:
|
||||
typedef mozilla::image::ImageURL ImageURL;
|
||||
imgRequest(imgLoader* aLoader);
|
||||
virtual ~imgRequest();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
nsresult Init(nsIURI *aURI,
|
||||
nsIURI *aCurrentURI,
|
||||
@ -121,7 +126,8 @@ public:
|
||||
// Update the cache entry size based on the image container
|
||||
void UpdateCacheEntrySize();
|
||||
|
||||
nsresult GetURI(nsIURI **aURI);
|
||||
// OK to use on any thread.
|
||||
nsresult GetURI(ImageURL **aURI);
|
||||
|
||||
private:
|
||||
friend class imgCacheEntry;
|
||||
@ -176,11 +182,15 @@ private:
|
||||
|
||||
public:
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
|
||||
// Sets properties for this image; will dispatch to main thread if needed.
|
||||
void SetProperties(nsIChannel* aChan);
|
||||
|
||||
private:
|
||||
friend class imgMemoryReporter;
|
||||
|
||||
@ -188,8 +198,9 @@ private:
|
||||
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.
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
// keyed on in the cache. We store a string here to avoid off main thread
|
||||
// refcounting issues with nsStandardURL.
|
||||
nsRefPtr<ImageURL> mURI;
|
||||
// The URI of the resource we ended up loading after all redirects, etc.
|
||||
nsCOMPtr<nsIURI> mCurrentURI;
|
||||
// The principal of the document which loaded this image. Used when validating for CORS.
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "ImageLogging.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "imgINotificationObserver.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
using namespace mozilla::image;
|
||||
|
||||
@ -146,7 +147,7 @@ imgRequestProxy::~imgRequestProxy()
|
||||
|
||||
nsresult imgRequestProxy::Init(imgRequest* aOwner,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
imgINotificationObserver* aObserver)
|
||||
{
|
||||
NS_PRECONDITION(!GetOwner() && !mListener, "imgRequestProxy is already initialized");
|
||||
@ -503,6 +504,14 @@ NS_IMETHODIMP imgRequestProxy::GetImageStatus(uint32_t *aStatus)
|
||||
|
||||
/* readonly attribute nsIURI URI; */
|
||||
NS_IMETHODIMP imgRequestProxy::GetURI(nsIURI **aURI)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread to convert URI");
|
||||
nsCOMPtr<nsIURI> uri = mURI->ToIURI();
|
||||
uri.forget(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult imgRequestProxy::GetURI(ImageURL **aURI)
|
||||
{
|
||||
if (!mURI)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -36,6 +36,7 @@ class ProxyBehaviour;
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
class Image;
|
||||
class ImageURL;
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
@ -45,6 +46,7 @@ class imgRequestProxy : public imgIRequest,
|
||||
public nsITimedChannel
|
||||
{
|
||||
public:
|
||||
typedef mozilla::image::ImageURL ImageURL;
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IMGIREQUEST
|
||||
NS_DECL_NSIREQUEST
|
||||
@ -59,7 +61,7 @@ public:
|
||||
// (although not immediately after) doing so.
|
||||
nsresult Init(imgRequest* aOwner,
|
||||
nsILoadGroup *aLoadGroup,
|
||||
nsIURI* aURI,
|
||||
ImageURL* aURI,
|
||||
imgINotificationObserver *aObserver);
|
||||
|
||||
nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous
|
||||
@ -106,6 +108,8 @@ public:
|
||||
virtual nsresult Clone(imgINotificationObserver* aObserver, imgRequestProxy** aClone);
|
||||
nsresult GetStaticRequest(imgRequestProxy** aReturn);
|
||||
|
||||
nsresult GetURI(ImageURL **aURI);
|
||||
|
||||
protected:
|
||||
friend class imgStatusTracker;
|
||||
friend class imgStatusNotifyRunnable;
|
||||
@ -194,7 +198,7 @@ private:
|
||||
friend imgRequestProxy* NewStaticProxy(imgRequestProxy* aThis);
|
||||
|
||||
// The URI of our request.
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsRefPtr<ImageURL> mURI;
|
||||
|
||||
// mListener is only promised to be a weak ref (see imgILoader.idl),
|
||||
// but we actually keep a strong ref to it until we've seen our
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "imgDecoderObserver.h"
|
||||
#include "Image.h"
|
||||
#include "ImageLogging.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
@ -391,7 +392,7 @@ imgStatusTracker::Notify(imgRequestProxy* proxy)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (GetImage() && GetImage()->GetURI()) {
|
||||
nsCOMPtr<nsIURI> uri(GetImage()->GetURI());
|
||||
nsRefPtr<ImageURL> uri(GetImage()->GetURI());
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
LOG_FUNC_WITH_PARAM(GetImgLog(), "imgStatusTracker::Notify async", "uri", spec.get());
|
||||
@ -444,7 +445,7 @@ void
|
||||
imgStatusTracker::NotifyCurrentState(imgRequestProxy* proxy)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsRefPtr<ImageURL> uri;
|
||||
proxy->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
@ -632,7 +633,7 @@ void
|
||||
imgStatusTracker::SyncNotify(imgRequestProxy* proxy)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsRefPtr<ImageURL> uri;
|
||||
proxy->GetURI(getter_AddRefs(uri));
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
@ -1071,7 +1072,12 @@ imgStatusTracker::FireFailureNotification()
|
||||
// Some kind of problem has happened with image decoding.
|
||||
// Report the URI to net:failed-to-process-uri-conent observers.
|
||||
if (GetImage()) {
|
||||
nsCOMPtr<nsIURI> uri = GetImage()->GetURI();
|
||||
// Should be on main thread, so ok to create a new nsIURI.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
{
|
||||
nsRefPtr<ImageURL> threadsafeUriData = GetImage()->GetURI();
|
||||
uri = threadsafeUriData ? threadsafeUriData->ToIURI() : nullptr;
|
||||
}
|
||||
if (uri) {
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (os) {
|
||||
|
@ -25,6 +25,12 @@ nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsIURI* aURI)
|
||||
Parse(ref);
|
||||
}
|
||||
|
||||
nsMediaFragmentURIParser::nsMediaFragmentURIParser(nsCString& aRef)
|
||||
: mClipUnit(eClipUnit_Pixel)
|
||||
{
|
||||
Parse(aRef);
|
||||
}
|
||||
|
||||
bool nsMediaFragmentURIParser::ParseNPT(nsDependentSubstring aString)
|
||||
{
|
||||
nsDependentSubstring original(aString);
|
||||
|
@ -35,6 +35,9 @@ public:
|
||||
// Create a parser with the provided URI.
|
||||
nsMediaFragmentURIParser(nsIURI* aURI);
|
||||
|
||||
// Create a parser with the provided URI reference portion.
|
||||
nsMediaFragmentURIParser(nsCString& aRef);
|
||||
|
||||
// True if a valid temporal media fragment indicated a start time.
|
||||
bool HasStartTime() const { return !mStart.empty(); }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user