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 https://mozilla.org/MPL/2.0/. */
6 
7 #include "AudioWorkletImpl.h"
8 
9 #include "AudioContext.h"
10 #include "AudioNodeTrack.h"
11 #include "GeckoProfiler.h"
12 #include "mozilla/dom/AudioWorkletBinding.h"
13 #include "mozilla/dom/AudioWorkletGlobalScope.h"
14 #include "mozilla/dom/Worklet.h"
15 #include "mozilla/dom/WorkletThread.h"
16 #include "nsGlobalWindowInner.h"
17 
18 namespace mozilla {
19 
CreateWorklet(dom::AudioContext * aContext,ErrorResult & aRv)20 /* static */ already_AddRefed<dom::Worklet> AudioWorkletImpl::CreateWorklet(
21     dom::AudioContext* aContext, ErrorResult& aRv) {
22   MOZ_ASSERT(NS_IsMainThread());
23 
24   nsCOMPtr<nsPIDOMWindowInner> window = aContext->GetOwner();
25   if (NS_WARN_IF(!window)) {
26     aRv.Throw(NS_ERROR_FAILURE);
27     return nullptr;
28   }
29   nsCOMPtr<nsIPrincipal> principal =
30       nsGlobalWindowInner::Cast(window)->GetPrincipal();
31   if (NS_WARN_IF(!principal)) {
32     aRv.Throw(NS_ERROR_FAILURE);
33     return nullptr;
34   }
35 
36   RefPtr<AudioWorkletImpl> impl =
37       new AudioWorkletImpl(window, principal, aContext->DestinationTrack());
38 
39   // The Worklet owns a reference to the AudioContext so as to keep the graph
40   // thread running as long as the Worklet is alive by keeping the
41   // AudioDestinationNode alive.
42   return MakeAndAddRef<dom::Worklet>(window, std::move(impl),
43                                      ToSupports(aContext));
44 }
45 
AudioWorkletImpl(nsPIDOMWindowInner * aWindow,nsIPrincipal * aPrincipal,AudioNodeTrack * aDestinationTrack)46 AudioWorkletImpl::AudioWorkletImpl(nsPIDOMWindowInner* aWindow,
47                                    nsIPrincipal* aPrincipal,
48                                    AudioNodeTrack* aDestinationTrack)
49     : WorkletImpl(aWindow, aPrincipal), mDestinationTrack(aDestinationTrack) {}
50 
51 AudioWorkletImpl::~AudioWorkletImpl() = default;
52 
WrapWorklet(JSContext * aCx,dom::Worklet * aWorklet,JS::Handle<JSObject * > aGivenProto)53 JSObject* AudioWorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
54                                         JS::Handle<JSObject*> aGivenProto) {
55   MOZ_ASSERT(NS_IsMainThread());
56   return dom::AudioWorklet_Binding::Wrap(aCx, aWorklet, aGivenProto);
57 }
58 
SendControlMessage(already_AddRefed<nsIRunnable> aRunnable)59 nsresult AudioWorkletImpl::SendControlMessage(
60     already_AddRefed<nsIRunnable> aRunnable) {
61   mDestinationTrack->SendRunnable(std::move(aRunnable));
62   return NS_OK;
63 }
64 
OnAddModuleStarted() const65 void AudioWorkletImpl::OnAddModuleStarted() const {
66 #ifdef MOZ_GECKO_PROFILER
67   profiler_add_marker(ProfilerStringView("AudioWorklet.addModule"),
68                       geckoprofiler::category::MEDIA_RT,
69                       {MarkerTiming::IntervalStart()});
70 #endif
71 }
72 
OnAddModulePromiseSettled() const73 void AudioWorkletImpl::OnAddModulePromiseSettled() const {
74 #ifdef MOZ_GECKO_PROFILER
75   profiler_add_marker(ProfilerStringView("AudioWorklet.addModule"),
76                       geckoprofiler::category::MEDIA_RT,
77                       {MarkerTiming::IntervalEnd()});
78 #endif
79 }
80 
81 already_AddRefed<dom::WorkletGlobalScope>
ConstructGlobalScope()82 AudioWorkletImpl::ConstructGlobalScope() {
83   dom::WorkletThread::AssertIsOnWorkletThread();
84 
85   return MakeAndAddRef<dom::AudioWorkletGlobalScope>(this);
86 }
87 
88 }  // namespace mozilla
89