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 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 #if !defined(BufferMediaResource_h_)
7 #define BufferMediaResource_h_
9 #include "MediaResource.h"
10 #include "nsISeekableStream.h"
11 #include "nsIPrincipal.h"
12 #include <algorithm>
14 namespace mozilla {
16 // A simple MediaResource based on an in memory buffer. This class accepts
17 // the address and the length of the buffer, and simulates a read/seek API
18 // on top of it. The Read implementation involves copying memory, which is
19 // unfortunate, but the MediaResource interface mandates that.
20 class BufferMediaResource : public MediaResource
21 {
22 public:
23 BufferMediaResource(const uint8_t* aBuffer,
24 uint32_t aLength,
25 nsIPrincipal* aPrincipal,
26 const nsACString& aContentType) :
27 mBuffer(aBuffer),
28 mLength(aLength),
29 mOffset(0),
30 mPrincipal(aPrincipal),
31 mContentType(aContentType)
32 {
33 MOZ_COUNT_CTOR(BufferMediaResource);
34 }
36 virtual ~BufferMediaResource()
37 {
38 MOZ_COUNT_DTOR(BufferMediaResource);
39 }
41 virtual nsresult Close() { return NS_OK; }
42 virtual void Suspend(bool aCloseImmediately) {}
43 virtual void Resume() {}
44 // Get the current principal for the channel
45 virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal()
46 {
47 nsCOMPtr<nsIPrincipal> principal = mPrincipal;
48 return principal.forget();
49 }
50 virtual bool CanClone() { return false; }
51 virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder)
52 {
53 return nullptr;
54 }
56 // These methods are called off the main thread.
57 // The mode is initially MODE_PLAYBACK.
58 virtual void SetReadMode(MediaCacheStream::ReadMode aMode) {}
59 virtual void SetPlaybackRate(uint32_t aBytesPerSecond) {}
60 virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
61 {
62 *aBytes = std::min(mLength - mOffset, aCount);
63 memcpy(aBuffer, mBuffer + mOffset, *aBytes);
64 mOffset += *aBytes;
65 MOZ_ASSERT(mOffset <= mLength);
66 return NS_OK;
67 }
68 virtual nsresult ReadAt(int64_t aOffset, char* aBuffer,
69 uint32_t aCount, uint32_t* aBytes)
70 {
71 nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
72 if (NS_FAILED(rv)) return rv;
73 return Read(aBuffer, aCount, aBytes);
74 }
75 virtual nsresult Seek(int32_t aWhence, int64_t aOffset)
76 {
77 MOZ_ASSERT(aOffset <= UINT32_MAX);
78 switch (aWhence) {
79 case nsISeekableStream::NS_SEEK_SET:
80 if (aOffset < 0 || aOffset > mLength) {
81 return NS_ERROR_FAILURE;
82 }
83 mOffset = static_cast<uint32_t> (aOffset);
84 break;
85 case nsISeekableStream::NS_SEEK_CUR:
86 if (aOffset >= mLength - mOffset) {
87 return NS_ERROR_FAILURE;
88 }
89 mOffset += static_cast<uint32_t> (aOffset);
90 break;
91 case nsISeekableStream::NS_SEEK_END:
92 if (aOffset < 0 || aOffset > mLength) {
93 return NS_ERROR_FAILURE;
94 }
95 mOffset = mLength - aOffset;
96 break;
97 }
99 return NS_OK;
100 }
101 virtual void StartSeekingForMetadata() {}
102 virtual void EndSeekingForMetadata() {}
103 virtual int64_t Tell() { return mOffset; }
105 virtual void Pin() {}
106 virtual void Unpin() {}
107 virtual double GetDownloadRate(bool* aIsReliable) { return 0.; }
108 virtual int64_t GetLength() { return mLength; }
109 virtual int64_t GetNextCachedData(int64_t aOffset) { return aOffset; }
110 virtual int64_t GetCachedDataEnd(int64_t aOffset) { return mLength; }
111 virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
112 virtual bool IsSuspendedByCache() { return false; }
113 virtual bool IsSuspended() { return false; }
114 virtual nsresult ReadFromCache(char* aBuffer,
115 int64_t aOffset,
116 uint32_t aCount)
117 {
118 if (aOffset < 0) {
119 return NS_ERROR_FAILURE;
120 }
122 uint32_t bytes = std::min(mLength - static_cast<uint32_t>(aOffset), aCount);
123 memcpy(aBuffer, mBuffer + aOffset, bytes);
124 return NS_OK;
125 }
127 virtual nsresult Open(nsIStreamListener** aStreamListener)
128 {
129 return NS_ERROR_FAILURE;
130 }
132 virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges)
133 {
134 aRanges.AppendElement(MediaByteRange(0, mLength));
135 return NS_OK;
136 }
138 bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
140 virtual const nsCString& GetContentType() const MOZ_OVERRIDE
141 {
142 return mContentType;
143 }
145 virtual size_t SizeOfExcludingThis(
146 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
147 {
148 // Not owned:
149 // - mBuffer
150 // - mPrincipal
151 size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
152 size += mContentType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
154 return size;
155 }
157 virtual size_t SizeOfIncludingThis(
158 MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
159 {
160 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
161 }
163 private:
164 const uint8_t * mBuffer;
165 uint32_t mLength;
166 uint32_t mOffset;
167 nsCOMPtr<nsIPrincipal> mPrincipal;
168 const nsAutoCString mContentType;
169 };
171 }
173 #endif