Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
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: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef GFX_READBACKLAYER_H
7 #define GFX_READBACKLAYER_H
9 #include <stdint.h> // for uint64_t
10 #include "Layers.h" // for Layer, etc
11 #include "gfxColor.h" // for gfxRGBA
12 #include "gfxRect.h" // for gfxRect
13 #include "mozilla/mozalloc.h" // for operator delete
14 #include "nsAutoPtr.h" // for nsAutoPtr
15 #include "nsCOMPtr.h" // for already_AddRefed
16 #include "nsDebug.h" // for NS_ASSERTION
17 #include "nsPoint.h" // for nsIntPoint
18 #include "nsRect.h" // for nsIntRect
19 #include "nsSize.h" // for nsIntSize
20 #include "nscore.h" // for nsACString
22 class gfxContext;
24 namespace mozilla {
25 namespace layers {
27 class ReadbackProcessor;
29 /**
30 * A ReadbackSink receives a stream of updates to a rectangle of pixels.
31 * These update callbacks are always called on the main thread, either during
32 * EndTransaction or from the event loop.
33 */
34 class ReadbackSink {
35 public:
36 ReadbackSink() {}
37 virtual ~ReadbackSink() {}
39 /**
40 * Sends an update to indicate that the background is currently unknown.
41 */
42 virtual void SetUnknown(uint64_t aSequenceNumber) = 0;
43 /**
44 * Called by the layer system to indicate that the contents of part of
45 * the readback area are changing.
46 * @param aRect is the rectangle of content that is being updated,
47 * in the coordinate system of the ReadbackLayer.
48 * @param aSequenceNumber updates issued out of order should be ignored.
49 * Only use updates whose sequence counter is greater than all other updates
50 * seen so far. Return null when a non-fresh sequence value is given.
51 * @return a context into which the update should be drawn. This should be
52 * set up to clip to aRect. Zero should never be passed as a sequence number.
53 * If this returns null, EndUpdate should NOT be called. If it returns
54 * non-null, EndUpdate must be called.
55 *
56 * We don't support partially unknown backgrounds. Therefore, the
57 * first BeginUpdate after a SetUnknown will have the complete background.
58 */
59 virtual already_AddRefed<gfxContext>
60 BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber) = 0;
61 /**
62 * EndUpdate must be called immediately after BeginUpdate, without returning
63 * to the event loop.
64 * @param aContext the context returned by BeginUpdate
65 * Implicitly Restore()s the state of aContext.
66 */
67 virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect) = 0;
68 };
70 /**
71 * A ReadbackLayer never renders anything. It enables clients to extract
72 * the rendered contents of the layer tree below the ReadbackLayer.
73 * The rendered contents are delivered asynchronously via calls to a
74 * ReadbackSink object supplied by the client.
75 *
76 * This is a "best effort" API; it is possible for the layer system to tell
77 * the ReadbackSink that the contents of the readback area are unknown.
78 *
79 * This API exists to work around the limitations of transparent windowless
80 * plugin rendering APIs. It should not be used for anything else.
81 */
82 class ReadbackLayer : public Layer {
83 public:
84 MOZ_LAYER_DECL_NAME("ReadbackLayer", TYPE_READBACK)
86 virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
87 {
88 // Snap our local transform first, and snap the inherited transform as well.
89 // This makes our snapping equivalent to what would happen if our content
90 // was drawn into a ThebesLayer (gfxContext would snap using the local
91 // transform, then we'd snap again when compositing the ThebesLayer).
92 mEffectiveTransform =
93 SnapTransform(GetLocalTransform(), gfxRect(0, 0, mSize.width, mSize.height),
94 nullptr)*
95 SnapTransformTranslation(aTransformToSurface, nullptr);
96 }
98 /**
99 * CONSTRUCTION PHASE ONLY
100 * Set the callback object to which readback updates will be delivered.
101 * This also resets the "needed rectangle" so that on the next layer tree
102 * transaction we will try to deliver the full contents of the readback
103 * area to the sink.
104 * This layer takes ownership of the sink. It will be deleted when the
105 * layer is destroyed or when a new sink is set.
106 * Initially the contents of the readback area are completely unknown.
107 */
108 void SetSink(ReadbackSink* aSink)
109 {
110 SetUnknown();
111 mSink = aSink;
112 }
113 ReadbackSink* GetSink() { return mSink; }
115 /**
116 * CONSTRUCTION PHASE ONLY
117 * Set the size of content that should be read back. The readback area
118 * has its top-left at 0,0 and has size aSize.
119 * Can only be called while the sink is null!
120 */
121 void SetSize(const nsIntSize& aSize)
122 {
123 NS_ASSERTION(!mSink, "Should have no sink while changing size!");
124 mSize = aSize;
125 }
126 const nsIntSize& GetSize() { return mSize; }
127 nsIntRect GetRect() { return nsIntRect(nsIntPoint(0, 0), mSize); }
129 bool IsBackgroundKnown()
130 {
131 return mBackgroundLayer || mBackgroundColor.a == 1.0;
132 }
134 void NotifyRemoved() {
135 SetUnknown();
136 mSink = nullptr;
137 }
139 void NotifyThebesLayerRemoved(ThebesLayer* aLayer)
140 {
141 if (mBackgroundLayer == aLayer) {
142 mBackgroundLayer = nullptr;
143 }
144 }
146 const nsIntPoint& GetBackgroundLayerOffset() { return mBackgroundLayerOffset; }
148 uint64_t AllocateSequenceNumber() { return ++mSequenceCounter; }
150 void SetUnknown()
151 {
152 if (IsBackgroundKnown()) {
153 if (mSink) {
154 mSink->SetUnknown(AllocateSequenceNumber());
155 }
156 mBackgroundLayer = nullptr;
157 mBackgroundColor = gfxRGBA(0,0,0,0);
158 }
159 }
161 protected:
162 friend class ReadbackProcessor;
164 ReadbackLayer(LayerManager* aManager, void* aImplData) :
165 Layer(aManager, aImplData),
166 mSequenceCounter(0),
167 mSize(0,0),
168 mBackgroundLayer(nullptr),
169 mBackgroundLayerOffset(0, 0),
170 mBackgroundColor(gfxRGBA(0,0,0,0))
171 {}
173 // Print interesting information about this into aTo. Internally
174 // used to implement Dump*() and Log*().
175 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
177 uint64_t mSequenceCounter;
178 nsAutoPtr<ReadbackSink> mSink;
179 nsIntSize mSize;
181 // This can refer to any (earlier) sibling ThebesLayer. That ThebesLayer
182 // must have mUsedForReadback set on it. If the ThebesLayer is removed
183 // for the container, this will be set to null by NotifyThebesLayerRemoved.
184 // This ThebesLayer contains the contents which have previously been reported
185 // to mSink. The ThebesLayer had only an integer translation transform,
186 // and it covered the entire readback area. This layer also had only an
187 // integer translation transform.
188 ThebesLayer* mBackgroundLayer;
189 // When mBackgroundLayer is non-null, this is the offset to add to
190 // convert from the coordinates of mBackgroundLayer to the coordinates
191 // of this layer.
192 nsIntPoint mBackgroundLayerOffset;
193 // When mBackgroundColor is opaque, this is the color of the ColorLayer
194 // that contained the contents we reported to mSink, which covered the
195 // entire readback area.
196 gfxRGBA mBackgroundColor;
197 };
199 }
200 }
201 #endif /* GFX_READBACKLAYER_H */