no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / dom / media / CloneableWithRangeMediaResource.cpp
blob4faac6125fd4e1d0401e4acabfa671552d480115
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 #include "CloneableWithRangeMediaResource.h"
8 #include "mozilla/AbstractThread.h"
9 #include "mozilla/Monitor.h"
10 #include "nsContentUtils.h"
11 #include "nsIAsyncInputStream.h"
12 #include "nsITimedChannel.h"
13 #include "nsNetCID.h"
14 #include "nsServiceManagerUtils.h"
16 namespace mozilla {
18 namespace {
20 class InputStreamReader final : public nsIInputStreamCallback {
21 public:
22 NS_DECL_THREADSAFE_ISUPPORTS
24 static already_AddRefed<InputStreamReader> Create(
25 nsICloneableInputStreamWithRange* aStream, int64_t aStart,
26 uint32_t aLength) {
27 MOZ_ASSERT(aStream);
29 nsCOMPtr<nsIInputStream> stream;
30 nsresult rv =
31 aStream->CloneWithRange(aStart, aLength, getter_AddRefs(stream));
32 if (NS_WARN_IF(NS_FAILED(rv))) {
33 return nullptr;
36 RefPtr<InputStreamReader> reader = new InputStreamReader(stream);
37 return reader.forget();
40 nsresult Read(char* aBuffer, uint32_t aSize, uint32_t* aRead) {
41 uint32_t done = 0;
42 do {
43 uint32_t read;
44 nsresult rv = SyncRead(aBuffer + done, aSize - done, &read);
45 if (NS_SUCCEEDED(rv) && read == 0) {
46 break;
48 if (NS_WARN_IF(NS_FAILED(rv))) {
49 return rv;
51 done += read;
52 } while (done != aSize);
54 *aRead = done;
55 return NS_OK;
58 NS_IMETHOD
59 OnInputStreamReady(nsIAsyncInputStream* aStream) override {
60 // Let's continue with SyncRead().
61 MonitorAutoLock lock(mMonitor);
62 lock.Notify();
63 return NS_OK;
66 private:
67 explicit InputStreamReader(nsIInputStream* aStream)
68 : mStream(aStream), mMonitor("InputStreamReader::mMonitor") {
69 MOZ_ASSERT(aStream);
72 ~InputStreamReader() = default;
74 nsresult SyncRead(char* aBuffer, uint32_t aSize, uint32_t* aRead) {
75 while (1) {
76 nsresult rv = mStream->Read(aBuffer, aSize, aRead);
77 // All good.
78 if (rv == NS_BASE_STREAM_CLOSED || NS_SUCCEEDED(rv)) {
79 return NS_OK;
82 // An error.
83 if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
84 return rv;
87 // We need to proceed async.
88 if (!mAsyncStream) {
89 mAsyncStream = do_QueryInterface(mStream);
92 if (!mAsyncStream) {
93 return NS_ERROR_FAILURE;
96 nsCOMPtr<nsIEventTarget> target =
97 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
98 MOZ_ASSERT(target);
101 // We wait for ::OnInputStreamReady() to be called.
102 MonitorAutoLock lock(mMonitor);
104 rv = mAsyncStream->AsyncWait(this, 0, aSize, target);
105 if (NS_WARN_IF(NS_FAILED(rv))) {
106 return rv;
109 lock.Wait();
114 nsCOMPtr<nsIInputStream> mStream;
115 nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
116 Monitor mMonitor MOZ_UNANNOTATED;
119 NS_IMPL_ADDREF(InputStreamReader);
120 NS_IMPL_RELEASE(InputStreamReader);
122 NS_INTERFACE_MAP_BEGIN(InputStreamReader)
123 NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
124 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStreamCallback)
125 NS_INTERFACE_MAP_END
127 } // namespace
129 void CloneableWithRangeMediaResource::MaybeInitialize() {
130 if (!mInitialized) {
131 mInitialized = true;
132 mCallback->AbstractMainThread()->Dispatch(NewRunnableMethod<nsresult>(
133 "MediaResourceCallback::NotifyDataEnded", mCallback.get(),
134 &MediaResourceCallback::NotifyDataEnded, NS_OK));
138 nsresult CloneableWithRangeMediaResource::GetCachedRanges(
139 MediaByteRangeSet& aRanges) {
140 MaybeInitialize();
141 aRanges += MediaByteRange(0, (int64_t)mSize);
142 return NS_OK;
145 nsresult CloneableWithRangeMediaResource::Open(
146 nsIStreamListener** aStreamListener) {
147 MOZ_ASSERT(NS_IsMainThread());
148 MOZ_ASSERT(aStreamListener);
150 *aStreamListener = nullptr;
151 return NS_OK;
154 RefPtr<GenericPromise> CloneableWithRangeMediaResource::Close() {
155 return GenericPromise::CreateAndResolve(true, __func__);
158 already_AddRefed<nsIPrincipal>
159 CloneableWithRangeMediaResource::GetCurrentPrincipal() {
160 MOZ_ASSERT(NS_IsMainThread());
162 nsCOMPtr<nsIPrincipal> principal;
163 nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
164 if (!secMan || !mChannel) {
165 return nullptr;
168 secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(principal));
169 return principal.forget();
172 bool CloneableWithRangeMediaResource::HadCrossOriginRedirects() {
173 MOZ_ASSERT(NS_IsMainThread());
175 nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(mChannel);
176 if (!timedChannel) {
177 return false;
180 bool allRedirectsSameOrigin = false;
181 return NS_SUCCEEDED(timedChannel->GetAllRedirectsSameOrigin(
182 &allRedirectsSameOrigin)) &&
183 !allRedirectsSameOrigin;
186 nsresult CloneableWithRangeMediaResource::ReadFromCache(char* aBuffer,
187 int64_t aOffset,
188 uint32_t aCount) {
189 MaybeInitialize();
190 if (!aCount) {
191 return NS_OK;
194 RefPtr<InputStreamReader> reader =
195 InputStreamReader::Create(mStream, aOffset, aCount);
196 if (!reader) {
197 return NS_ERROR_FAILURE;
200 uint32_t bytes = 0;
201 nsresult rv = reader->Read(aBuffer, aCount, &bytes);
202 if (NS_WARN_IF(NS_FAILED(rv))) {
203 return rv;
206 return bytes == aCount ? NS_OK : NS_ERROR_FAILURE;
209 nsresult CloneableWithRangeMediaResource::ReadAt(int64_t aOffset, char* aBuffer,
210 uint32_t aCount,
211 uint32_t* aBytes) {
212 MOZ_ASSERT(!NS_IsMainThread());
214 RefPtr<InputStreamReader> reader =
215 InputStreamReader::Create(mStream, aOffset, aCount);
216 if (!reader) {
217 return NS_ERROR_FAILURE;
220 nsresult rv = reader->Read(aBuffer, aCount, aBytes);
221 if (NS_WARN_IF(NS_FAILED(rv))) {
222 return rv;
225 return NS_OK;
228 } // namespace mozilla