/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 |