Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/CloneableWithRangeMediaResource.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
5
6
#include "CloneableWithRangeMediaResource.h"
7
8
#include "mozilla/AbstractThread.h"
9
#include "mozilla/Monitor.h"
10
#include "nsContentUtils.h"
11
#include "nsIAsyncInputStream.h"
12
#include "nsNetCID.h"
13
14
namespace mozilla {
15
16
namespace {
17
18
class InputStreamReader final : public nsIInputStreamCallback
19
{
20
public:
21
  NS_DECL_THREADSAFE_ISUPPORTS
22
23
  static already_AddRefed<InputStreamReader>
24
  Create(nsICloneableInputStreamWithRange* aStream, int64_t aStart,
25
         uint32_t aLength)
26
0
  {
27
0
    MOZ_ASSERT(aStream);
28
0
29
0
    nsCOMPtr<nsIInputStream> stream;
30
0
    nsresult rv = aStream->CloneWithRange(aStart, aLength,
31
0
                                          getter_AddRefs(stream));
32
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
33
0
      return nullptr;
34
0
    }
35
0
36
0
    RefPtr<InputStreamReader> reader = new InputStreamReader(stream);
37
0
    return reader.forget();
38
0
  }
39
40
  nsresult
41
  Read(char* aBuffer, uint32_t aSize, uint32_t* aRead)
42
0
  {
43
0
    uint32_t done = 0;
44
0
    do {
45
0
      uint32_t read;
46
0
      nsresult rv = SyncRead(aBuffer + done, aSize - done, &read);
47
0
      if (NS_SUCCEEDED(rv) && read == 0) {
48
0
        break;
49
0
      }
50
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
51
0
        return rv;
52
0
      }
53
0
      done += read;
54
0
    } while(done != aSize);
55
0
56
0
    *aRead = done;
57
0
    return NS_OK;
58
0
  }
59
60
  NS_IMETHOD
61
  OnInputStreamReady(nsIAsyncInputStream* aStream) override
62
0
  {
63
0
    // Let's continue with SyncRead().
64
0
    MonitorAutoLock lock(mMonitor);
65
0
    return lock.Notify();
66
0
  }
67
68
private:
69
  explicit InputStreamReader(nsIInputStream* aStream)
70
    : mStream(aStream)
71
    , mMonitor("InputStreamReader::mMonitor")
72
0
  {
73
0
    MOZ_ASSERT(aStream);
74
0
  }
75
76
0
  ~InputStreamReader() = default;
77
78
  nsresult
79
  SyncRead(char* aBuffer, uint32_t aSize, uint32_t* aRead)
80
0
  {
81
0
    while (1) {
82
0
      nsresult rv = mStream->Read(aBuffer, aSize, aRead);
83
0
      // All good.
84
0
      if (rv == NS_BASE_STREAM_CLOSED || NS_SUCCEEDED(rv)) {
85
0
        return NS_OK;
86
0
      }
87
0
88
0
      // An error.
89
0
      if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
90
0
        return rv;
91
0
      }
92
0
93
0
      // We need to proceed async.
94
0
      if (!mAsyncStream) {
95
0
        mAsyncStream = do_QueryInterface(mStream);
96
0
      }
97
0
98
0
      if (!mAsyncStream) {
99
0
        return NS_ERROR_FAILURE;
100
0
      }
101
0
102
0
      nsCOMPtr<nsIEventTarget> target =
103
0
        do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
104
0
      MOZ_ASSERT(target);
105
0
106
0
      {
107
0
        // We wait for ::OnInputStreamReady() to be called.
108
0
        MonitorAutoLock lock(mMonitor);
109
0
110
0
        rv = mAsyncStream->AsyncWait(this, 0, aSize, target);
111
0
        if (NS_WARN_IF(NS_FAILED(rv))) {
112
0
          return rv;
113
0
        }
114
0
115
0
        lock.Wait();
116
0
      }
117
0
    }
118
0
  }
119
120
  nsCOMPtr<nsIInputStream> mStream;
121
  nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
122
  Monitor mMonitor;
123
};
124
125
NS_IMPL_ADDREF(InputStreamReader);
126
NS_IMPL_RELEASE(InputStreamReader);
127
128
0
NS_INTERFACE_MAP_BEGIN(InputStreamReader)
129
0
  NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
130
0
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStreamCallback)
131
0
NS_INTERFACE_MAP_END
132
133
} // anonymous
134
135
void
136
CloneableWithRangeMediaResource::MaybeInitialize()
137
0
{
138
0
  if (!mInitialized) {
139
0
    mInitialized = true;
140
0
    mCallback->AbstractMainThread()->Dispatch(
141
0
      NewRunnableMethod<nsresult>("MediaResourceCallback::NotifyDataEnded",
142
0
                                  mCallback.get(),
143
0
                                  &MediaResourceCallback::NotifyDataEnded,
144
0
                                  NS_OK));
145
0
  }
146
0
}
147
148
nsresult
149
CloneableWithRangeMediaResource::GetCachedRanges(MediaByteRangeSet& aRanges)
150
0
{
151
0
  MaybeInitialize();
152
0
  aRanges += MediaByteRange(0, (int64_t)mSize);
153
0
  return NS_OK;
154
0
}
155
156
nsresult
157
CloneableWithRangeMediaResource::Open(nsIStreamListener** aStreamListener)
158
0
{
159
0
  MOZ_ASSERT(NS_IsMainThread());
160
0
  MOZ_ASSERT(aStreamListener);
161
0
162
0
  *aStreamListener = nullptr;
163
0
  return NS_OK;
164
0
}
165
166
nsresult
167
CloneableWithRangeMediaResource::Close()
168
0
{
169
0
  return NS_OK;
170
0
}
171
172
already_AddRefed<nsIPrincipal>
173
CloneableWithRangeMediaResource::GetCurrentPrincipal()
174
0
{
175
0
  MOZ_ASSERT(NS_IsMainThread());
176
0
177
0
  nsCOMPtr<nsIPrincipal> principal;
178
0
  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
179
0
  if (!secMan || !mChannel) {
180
0
    return nullptr;
181
0
  }
182
0
183
0
  secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(principal));
184
0
  return principal.forget();
185
0
}
186
187
nsresult
188
CloneableWithRangeMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset,
189
                                               uint32_t aCount)
190
0
{
191
0
  MaybeInitialize();
192
0
  if (!aCount) {
193
0
    return NS_OK;
194
0
  }
195
0
196
0
  RefPtr<InputStreamReader> reader =
197
0
    InputStreamReader::Create(mStream, aOffset, aCount);
198
0
  if (!reader) {
199
0
    return NS_ERROR_FAILURE;
200
0
  }
201
0
202
0
  uint32_t bytes = 0;
203
0
  nsresult rv = reader->Read(aBuffer, aCount, &bytes);
204
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
205
0
    return rv;
206
0
  }
207
0
208
0
  return bytes == aCount ? NS_OK : NS_ERROR_FAILURE;
209
0
}
210
211
nsresult
212
CloneableWithRangeMediaResource::ReadAt(int64_t aOffset, char* aBuffer,
213
                                        uint32_t aCount, uint32_t* aBytes)
214
0
{
215
0
  MOZ_ASSERT(!NS_IsMainThread());
216
0
217
0
  RefPtr<InputStreamReader> reader =
218
0
    InputStreamReader::Create(mStream, aOffset, aCount);
219
0
  if (!reader) {
220
0
    return NS_ERROR_FAILURE;
221
0
  }
222
0
223
0
  nsresult rv = reader->Read(aBuffer, aCount, aBytes);
224
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
225
0
    return rv;
226
0
  }
227
0
228
0
  return NS_OK;
229
0
}
230
231
} // mozilla namespace