Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/BaseMediaResource.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "BaseMediaResource.h"
2
3
#include "ChannelMediaResource.h"
4
#include "CloneableWithRangeMediaResource.h"
5
#include "FileMediaResource.h"
6
#include "MediaContainerType.h"
7
#include "mozilla/dom/BlobImpl.h"
8
#include "mozilla/dom/BlobURLProtocolHandler.h"
9
#include "mozilla/dom/HTMLMediaElement.h"
10
#include "nsDebug.h"
11
#include "nsError.h"
12
#include "nsICloneableInputStream.h"
13
#include "nsIFile.h"
14
#include "nsIFileChannel.h"
15
#include "nsIInputStream.h"
16
#include "nsISeekableStream.h"
17
#include "nsNetUtil.h"
18
19
namespace mozilla {
20
21
already_AddRefed<BaseMediaResource>
22
BaseMediaResource::Create(MediaResourceCallback* aCallback,
23
                          nsIChannel* aChannel,
24
                          bool aIsPrivateBrowsing)
25
0
{
26
0
  NS_ASSERTION(NS_IsMainThread(),
27
0
               "MediaResource::Open called on non-main thread");
28
0
29
0
  // If the channel was redirected, we want the post-redirect URI;
30
0
  // but if the URI scheme was expanded, say from chrome: to jar:file:,
31
0
  // we want the original URI.
32
0
  nsCOMPtr<nsIURI> uri;
33
0
  nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
34
0
  NS_ENSURE_SUCCESS(rv, nullptr);
35
0
36
0
  nsAutoCString contentTypeString;
37
0
  aChannel->GetContentType(contentTypeString);
38
0
  Maybe<MediaContainerType> containerType =
39
0
    MakeMediaContainerType(contentTypeString);
40
0
  if (!containerType) {
41
0
    return nullptr;
42
0
  }
43
0
44
0
  // Let's try to create a FileMediaResource in case the channel is a nsIFile
45
0
  nsCOMPtr<nsIFileChannel> fc = do_QueryInterface(aChannel);
46
0
  if (fc) {
47
0
    RefPtr<BaseMediaResource> resource =
48
0
      new FileMediaResource(aCallback, aChannel, uri);
49
0
    return resource.forget();
50
0
  }
51
0
52
0
  RefPtr<mozilla::dom::BlobImpl> blobImpl;
53
0
  if (dom::IsBlobURI(uri) &&
54
0
      NS_SUCCEEDED(NS_GetBlobForBlobURI(uri, getter_AddRefs(blobImpl))) &&
55
0
      blobImpl) {
56
0
    IgnoredErrorResult rv;
57
0
58
0
    nsCOMPtr<nsIInputStream> stream;
59
0
    blobImpl->CreateInputStream(getter_AddRefs(stream), rv);
60
0
    if (NS_WARN_IF(rv.Failed())) {
61
0
      return nullptr;
62
0
    }
63
0
64
0
    // It's better to read the size from the blob instead of using ::Available,
65
0
    // because, if the stream implements nsIAsyncInputStream interface,
66
0
    // ::Available will not return the size of the stream, but what can be
67
0
    // currently read.
68
0
    uint64_t size = blobImpl->GetSize(rv);
69
0
    if (NS_WARN_IF(rv.Failed())) {
70
0
      return nullptr;
71
0
    }
72
0
73
0
    // If the URL is a blob URL, with a seekable inputStream, we can still use
74
0
    // a FileMediaResource.
75
0
    nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(stream);
76
0
    if (seekableStream) {
77
0
      RefPtr<BaseMediaResource> resource =
78
0
        new FileMediaResource(aCallback, aChannel, uri, size);
79
0
      return resource.forget();
80
0
    }
81
0
82
0
    // Maybe this blob URL can be cloned with a range.
83
0
    nsCOMPtr<nsICloneableInputStreamWithRange> cloneableWithRange =
84
0
      do_QueryInterface(stream);
85
0
    if (cloneableWithRange) {
86
0
      RefPtr<BaseMediaResource> resource = new CloneableWithRangeMediaResource(
87
0
        aCallback, aChannel, uri, stream, size);
88
0
      return resource.forget();
89
0
    }
90
0
  }
91
0
92
0
  RefPtr<BaseMediaResource> resource =
93
0
    new ChannelMediaResource(aCallback, aChannel, uri, aIsPrivateBrowsing);
94
0
  return resource.forget();
95
0
}
96
97
void
98
BaseMediaResource::SetLoadInBackground(bool aLoadInBackground)
99
0
{
100
0
  if (aLoadInBackground == mLoadInBackground) {
101
0
    return;
102
0
  }
103
0
  mLoadInBackground = aLoadInBackground;
104
0
  if (!mChannel) {
105
0
    // No channel, resource is probably already loaded.
106
0
    return;
107
0
  }
108
0
109
0
  MediaDecoderOwner* owner = mCallback->GetMediaOwner();
110
0
  if (!owner) {
111
0
    NS_WARNING("Null owner in MediaResource::SetLoadInBackground()");
112
0
    return;
113
0
  }
114
0
  dom::HTMLMediaElement* element = owner->GetMediaElement();
115
0
  if (!element) {
116
0
    NS_WARNING("Null element in MediaResource::SetLoadInBackground()");
117
0
    return;
118
0
  }
119
0
120
0
  bool isPending = false;
121
0
  if (NS_SUCCEEDED(mChannel->IsPending(&isPending)) && isPending) {
122
0
    nsLoadFlags loadFlags;
123
0
    DebugOnly<nsresult> rv = mChannel->GetLoadFlags(&loadFlags);
124
0
    NS_ASSERTION(NS_SUCCEEDED(rv), "GetLoadFlags() failed!");
125
0
126
0
    if (aLoadInBackground) {
127
0
      loadFlags |= nsIRequest::LOAD_BACKGROUND;
128
0
    } else {
129
0
      loadFlags &= ~nsIRequest::LOAD_BACKGROUND;
130
0
    }
131
0
    ModifyLoadFlags(loadFlags);
132
0
  }
133
0
}
134
135
void
136
BaseMediaResource::ModifyLoadFlags(nsLoadFlags aFlags)
137
0
{
138
0
  nsCOMPtr<nsILoadGroup> loadGroup;
139
0
  nsresult rv = mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
140
0
  MOZ_ASSERT(NS_SUCCEEDED(rv), "GetLoadGroup() failed!");
141
0
142
0
  nsresult status;
143
0
  mChannel->GetStatus(&status);
144
0
145
0
  bool inLoadGroup = false;
146
0
  if (loadGroup) {
147
0
    rv = loadGroup->RemoveRequest(mChannel, nullptr, status);
148
0
    if (NS_SUCCEEDED(rv)) {
149
0
      inLoadGroup = true;
150
0
    }
151
0
  }
152
0
153
0
  rv = mChannel->SetLoadFlags(aFlags);
154
0
  MOZ_ASSERT(NS_SUCCEEDED(rv), "SetLoadFlags() failed!");
155
0
156
0
  if (inLoadGroup) {
157
0
    rv = loadGroup->AddRequest(mChannel, nullptr);
158
0
    MOZ_ASSERT(NS_SUCCEEDED(rv), "AddRequest() failed!");
159
0
  }
160
0
}
161
162
} // namespace mozilla