Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef imgFrame_h
8 #define imgFrame_h
10 #include "mozilla/MemoryReporting.h"
11 #include "mozilla/Mutex.h"
12 #include "mozilla/VolatileBuffer.h"
13 #include "nsRect.h"
14 #include "nsPoint.h"
15 #include "nsSize.h"
16 #include "gfxPattern.h"
17 #include "gfxDrawable.h"
18 #include "gfxImageSurface.h"
19 #if defined(XP_WIN)
20 #include "gfxWindowsSurface.h"
21 #elif defined(XP_MACOSX)
22 #include "gfxQuartzImageSurface.h"
23 #endif
24 #include "nsAutoPtr.h"
25 #include "imgIContainer.h"
26 #include "gfxColor.h"
28 /*
29 * This creates a gfxImageSurface which will unlock the buffer on destruction
30 */
32 class LockedImageSurface
33 {
34 public:
35 static gfxImageSurface *
36 CreateSurface(mozilla::VolatileBuffer *vbuf,
37 const gfxIntSize& size,
38 gfxImageFormat format);
39 static mozilla::TemporaryRef<mozilla::VolatileBuffer>
40 AllocateBuffer(const gfxIntSize& size, gfxImageFormat format);
41 };
43 class imgFrame
44 {
45 public:
46 imgFrame();
47 ~imgFrame();
49 nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, gfxImageFormat aFormat, uint8_t aPaletteDepth = 0);
50 nsresult Optimize();
52 bool Draw(gfxContext *aContext, GraphicsFilter aFilter,
53 const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
54 const nsIntMargin &aPadding, const nsIntRect &aSubimage,
55 uint32_t aImageFlags = imgIContainer::FLAG_NONE);
57 nsresult ImageUpdated(const nsIntRect &aUpdateRect);
58 bool GetIsDirty() const;
60 nsIntRect GetRect() const;
61 gfxImageFormat GetFormat() const;
62 bool GetNeedsBackground() const;
63 uint32_t GetImageBytesPerRow() const;
64 uint32_t GetImageDataLength() const;
65 bool GetIsPaletted() const;
66 bool GetHasAlpha() const;
67 void GetImageData(uint8_t **aData, uint32_t *length) const;
68 uint8_t* GetImageData() const;
69 void GetPaletteData(uint32_t **aPalette, uint32_t *length) const;
70 uint32_t* GetPaletteData() const;
72 int32_t GetRawTimeout() const;
73 void SetRawTimeout(int32_t aTimeout);
75 int32_t GetFrameDisposalMethod() const;
76 void SetFrameDisposalMethod(int32_t aFrameDisposalMethod);
77 int32_t GetBlendMethod() const;
78 void SetBlendMethod(int32_t aBlendMethod);
79 bool ImageComplete() const;
81 void SetHasNoAlpha();
82 void SetAsNonPremult(bool aIsNonPremult);
84 bool GetCompositingFailed() const;
85 void SetCompositingFailed(bool val);
87 nsresult LockImageData();
88 nsresult UnlockImageData();
89 void ApplyDirtToSurfaces();
91 void SetDiscardable();
93 nsresult GetSurface(gfxASurface **aSurface)
94 {
95 *aSurface = ThebesSurface();
96 NS_IF_ADDREF(*aSurface);
97 return NS_OK;
98 }
100 nsresult GetPattern(gfxPattern **aPattern)
101 {
102 if (mSinglePixel)
103 *aPattern = new gfxPattern(mSinglePixelColor);
104 else
105 *aPattern = new gfxPattern(ThebesSurface());
106 NS_ADDREF(*aPattern);
107 return NS_OK;
108 }
110 bool IsSinglePixel()
111 {
112 return mSinglePixel;
113 }
115 gfxASurface* CachedThebesSurface()
116 {
117 if (mOptSurface)
118 return mOptSurface;
119 #if defined(XP_WIN)
120 if (mWinSurface)
121 return mWinSurface;
122 #elif defined(XP_MACOSX)
123 if (mQuartzSurface)
124 return mQuartzSurface;
125 #endif
126 if (mImageSurface)
127 return mImageSurface;
128 return nullptr;
129 }
131 gfxASurface* ThebesSurface()
132 {
133 gfxASurface *sur = CachedThebesSurface();
134 if (sur)
135 return sur;
136 if (mVBuf) {
137 mozilla::VolatileBufferPtr<uint8_t> ref(mVBuf);
138 if (ref.WasBufferPurged())
139 return nullptr;
141 gfxImageSurface *imgSur =
142 LockedImageSurface::CreateSurface(mVBuf, mSize, mFormat);
143 #if defined(XP_MACOSX)
144 // Manually addref and release to make sure the cairo surface isn't lost
145 NS_ADDREF(imgSur);
146 gfxQuartzImageSurface *quartzSur = new gfxQuartzImageSurface(imgSur);
147 // quartzSur does not hold on to the gfxImageSurface
148 NS_RELEASE(imgSur);
149 return quartzSur;
150 #else
151 return imgSur;
152 #endif
153 }
154 // We can return null here if we're single pixel optimized
155 // or a paletted image. However, one has to check for paletted
156 // image data first before attempting to get a surface, so
157 // this is only valid for single pixel optimized images
158 MOZ_ASSERT(mSinglePixel, "No image surface and not a single pixel!");
159 return nullptr;
160 }
162 size_t SizeOfExcludingThisWithComputedFallbackIfHeap(
163 gfxMemoryLocation aLocation,
164 mozilla::MallocSizeOf aMallocSizeOf) const;
166 uint8_t GetPaletteDepth() const { return mPaletteDepth; }
167 uint32_t PaletteDataLength() const {
168 if (!mPaletteDepth)
169 return 0;
171 return ((1 << mPaletteDepth) * sizeof(uint32_t));
172 }
174 private: // methods
176 struct SurfaceWithFormat {
177 nsRefPtr<gfxDrawable> mDrawable;
178 gfxImageFormat mFormat;
179 SurfaceWithFormat() {}
180 SurfaceWithFormat(gfxDrawable* aDrawable, gfxImageFormat aFormat)
181 : mDrawable(aDrawable), mFormat(aFormat) {}
182 bool IsValid() { return !!mDrawable; }
183 };
185 SurfaceWithFormat SurfaceForDrawing(bool aDoPadding,
186 bool aDoPartialDecode,
187 bool aDoTile,
188 const nsIntMargin& aPadding,
189 gfxMatrix& aUserSpaceToImageSpace,
190 gfxRect& aFill,
191 gfxRect& aSubimage,
192 gfxRect& aSourceRect,
193 gfxRect& aImageRect,
194 gfxASurface* aSurface);
196 private: // data
197 nsRefPtr<gfxImageSurface> mImageSurface;
198 nsRefPtr<gfxASurface> mOptSurface;
199 #if defined(XP_WIN)
200 nsRefPtr<gfxWindowsSurface> mWinSurface;
201 #elif defined(XP_MACOSX)
202 nsRefPtr<gfxQuartzImageSurface> mQuartzSurface;
203 #endif
205 nsRefPtr<gfxASurface> mDrawSurface;
207 nsIntSize mSize;
208 nsIntPoint mOffset;
210 nsIntRect mDecoded;
212 mutable mozilla::Mutex mDirtyMutex;
214 // The palette and image data for images that are paletted, since Cairo
215 // doesn't support these images.
216 // The paletted data comes first, then the image data itself.
217 // Total length is PaletteDataLength() + GetImageDataLength().
218 uint8_t* mPalettedImageData;
220 // Note that the data stored in gfxRGBA is *non-alpha-premultiplied*.
221 gfxRGBA mSinglePixelColor;
223 int32_t mTimeout; // -1 means display forever
224 int32_t mDisposalMethod;
226 /** Indicates how many readers currently have locked this frame */
227 int32_t mLockCount;
229 mozilla::RefPtr<mozilla::VolatileBuffer> mVBuf;
231 gfxImageFormat mFormat;
232 uint8_t mPaletteDepth;
233 int8_t mBlendMethod;
234 bool mSinglePixel;
235 bool mFormatChanged;
236 bool mCompositingFailed;
237 bool mNonPremult;
238 bool mDiscardable;
240 /** Have we called DiscardTracker::InformAllocation()? */
241 bool mInformedDiscardTracker;
243 bool mDirty;
244 };
246 namespace mozilla {
247 namespace image {
248 // An RAII class to ensure it's easy to balance locks and unlocks on
249 // imgFrames.
250 class AutoFrameLocker
251 {
252 public:
253 AutoFrameLocker(imgFrame* frame)
254 : mFrame(frame)
255 , mSucceeded(NS_SUCCEEDED(frame->LockImageData()))
256 {}
258 ~AutoFrameLocker()
259 {
260 if (mSucceeded) {
261 mFrame->UnlockImageData();
262 }
263 }
265 // Whether the lock request succeeded.
266 bool Succeeded() { return mSucceeded; }
268 private:
269 imgFrame* mFrame;
270 bool mSucceeded;
271 };
272 }
273 }
275 #endif /* imgFrame_h */