Backed out changeset 06f41c22f3a6 (bug 1888460) for causing linux xpcshell failures...
[gecko.git] / dom / media / webaudio / MediaStreamTrackAudioSourceNode.cpp
blobf3948a33ad9bfdba73d549f5910c7f40498fd20a
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MediaStreamTrackAudioSourceNode.h"
8 #include "mozilla/dom/MediaStreamTrackAudioSourceNodeBinding.h"
9 #include "AudioNodeEngine.h"
10 #include "AudioNodeExternalInputTrack.h"
11 #include "AudioStreamTrack.h"
12 #include "mozilla/dom/Document.h"
13 #include "nsContentUtils.h"
14 #include "nsIScriptError.h"
16 namespace mozilla::dom {
18 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaStreamTrackAudioSourceNode)
20 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaStreamTrackAudioSourceNode)
21 tmp->Destroy();
22 NS_IMPL_CYCLE_COLLECTION_UNLINK(mInputTrack)
23 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_PTR
24 NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode)
26 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
27 MediaStreamTrackAudioSourceNode, AudioNode)
28 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInputTrack)
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamTrackAudioSourceNode)
32 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
34 NS_IMPL_ADDREF_INHERITED(MediaStreamTrackAudioSourceNode, AudioNode)
35 NS_IMPL_RELEASE_INHERITED(MediaStreamTrackAudioSourceNode, AudioNode)
37 MediaStreamTrackAudioSourceNode::MediaStreamTrackAudioSourceNode(
38 AudioContext* aContext)
39 : AudioNode(aContext, 2, ChannelCountMode::Max,
40 ChannelInterpretation::Speakers),
41 mTrackListener(this) {}
43 /* static */ already_AddRefed<MediaStreamTrackAudioSourceNode>
44 MediaStreamTrackAudioSourceNode::Create(
45 AudioContext& aAudioContext,
46 const MediaStreamTrackAudioSourceOptions& aOptions, ErrorResult& aRv) {
47 // The spec has a pointless check here. See
48 // https://github.com/WebAudio/web-audio-api/issues/2149
49 MOZ_RELEASE_ASSERT(!aAudioContext.IsOffline(), "Bindings messed up?");
51 if (!aOptions.mMediaStreamTrack->Ended() &&
52 aAudioContext.Graph() != aOptions.mMediaStreamTrack->Graph()) {
53 nsCOMPtr<nsPIDOMWindowInner> pWindow = aAudioContext.GetParentObject();
54 Document* document = pWindow ? pWindow->GetExtantDoc() : nullptr;
55 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "Web Audio"_ns,
56 document, nsContentUtils::eDOM_PROPERTIES,
57 "MediaStreamAudioSourceNodeDifferentRate");
58 // This is not a spec-required exception, just a limitation of our
59 // implementation.
60 aRv.ThrowNotSupportedError(
61 "Connecting AudioNodes from AudioContexts with different sample-rate "
62 "is currently not supported.");
63 return nullptr;
66 RefPtr<MediaStreamTrackAudioSourceNode> node =
67 new MediaStreamTrackAudioSourceNode(&aAudioContext);
69 node->Init(aOptions.mMediaStreamTrack, aRv);
70 if (aRv.Failed()) {
71 return nullptr;
74 return node.forget();
77 void MediaStreamTrackAudioSourceNode::Init(MediaStreamTrack* aMediaStreamTrack,
78 ErrorResult& aRv) {
79 MOZ_ASSERT(aMediaStreamTrack);
81 if (!aMediaStreamTrack->AsAudioStreamTrack()) {
82 aRv.ThrowInvalidStateError("\"mediaStreamTrack\" must be an audio track");
83 return;
86 if (aMediaStreamTrack->Ended()) {
87 // The track is ended and will never produce any data. Pretend like this is
88 // fine.
89 return;
92 MarkActive();
94 MediaTrackGraph* graph = Context()->Graph();
96 AudioNodeEngine* engine = new MediaStreamTrackAudioSourceNodeEngine(this);
97 mTrack = AudioNodeExternalInputTrack::Create(graph, engine);
99 MOZ_ASSERT(mTrack);
101 mInputTrack = aMediaStreamTrack;
102 ProcessedMediaTrack* outputTrack =
103 static_cast<ProcessedMediaTrack*>(mTrack.get());
104 mInputPort = mInputTrack->ForwardTrackContentsTo(outputTrack);
105 PrincipalChanged(mInputTrack); // trigger enabling/disabling of the connector
106 mInputTrack->AddPrincipalChangeObserver(this);
108 mInputTrack->AddConsumer(&mTrackListener);
111 void MediaStreamTrackAudioSourceNode::Destroy() {
112 if (mInputTrack) {
113 mTrackListener.NotifyEnded(mInputTrack);
114 mInputTrack->RemovePrincipalChangeObserver(this);
115 mInputTrack->RemoveConsumer(&mTrackListener);
116 mInputTrack = nullptr;
119 if (mInputPort) {
120 mInputPort->Destroy();
121 mInputPort = nullptr;
125 MediaStreamTrackAudioSourceNode::~MediaStreamTrackAudioSourceNode() {
126 Destroy();
130 * Changes the principal. Note that this will be called on the main thread, but
131 * changes will be enacted on the MediaTrackGraph thread. If the principal
132 * change results in the document principal losing access to the track, then
133 * there needs to be other measures in place to ensure that any media that is
134 * governed by the new track principal is not available to the MediaTrackGraph
135 * before this change completes. Otherwise, a site could get access to
136 * media that they are not authorized to receive.
138 * One solution is to block the altered content, call this method, then dispatch
139 * another change request to the MediaTrackGraph thread that allows the content
140 * under the new principal to flow. This might be unnecessary if the principal
141 * change is changing to be the document principal.
143 void MediaStreamTrackAudioSourceNode::PrincipalChanged(
144 MediaStreamTrack* aMediaStreamTrack) {
145 MOZ_ASSERT(aMediaStreamTrack == mInputTrack);
147 bool subsumes = false;
148 Document* doc = nullptr;
149 if (nsPIDOMWindowInner* parent = Context()->GetParentObject()) {
150 doc = parent->GetExtantDoc();
151 if (doc) {
152 nsIPrincipal* docPrincipal = doc->NodePrincipal();
153 nsIPrincipal* trackPrincipal = aMediaStreamTrack->GetPrincipal();
154 if (!trackPrincipal ||
155 NS_FAILED(docPrincipal->Subsumes(trackPrincipal, &subsumes))) {
156 subsumes = false;
160 auto track = static_cast<AudioNodeExternalInputTrack*>(mTrack.get());
161 bool enabled = subsumes;
162 track->SetInt32Parameter(MediaStreamTrackAudioSourceNodeEngine::ENABLE,
163 enabled);
164 fprintf(stderr, "NOW: %s", enabled ? "enabled" : "disabled");
166 if (!enabled && doc) {
167 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "Web Audio"_ns,
168 doc, nsContentUtils::eDOM_PROPERTIES,
169 CrossOriginErrorString());
173 size_t MediaStreamTrackAudioSourceNode::SizeOfExcludingThis(
174 MallocSizeOf aMallocSizeOf) const {
175 size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
176 if (mInputPort) {
177 amount += mInputPort->SizeOfIncludingThis(aMallocSizeOf);
179 return amount;
182 size_t MediaStreamTrackAudioSourceNode::SizeOfIncludingThis(
183 MallocSizeOf aMallocSizeOf) const {
184 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
187 void MediaStreamTrackAudioSourceNode::DestroyMediaTrack() {
188 if (mInputPort) {
189 mInputPort->Destroy();
190 mInputPort = nullptr;
192 AudioNode::DestroyMediaTrack();
195 JSObject* MediaStreamTrackAudioSourceNode::WrapObject(
196 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
197 return MediaStreamTrackAudioSourceNode_Binding::Wrap(aCx, this, aGivenProto);
200 } // namespace mozilla::dom