Bug 1850713: remove duplicated setting of early hint preloader id in `ScriptLoader...
[gecko.git] / dom / audiochannel / AudioChannelAgent.cpp
blob286888cc7871983df2ab31f876259cee6bc5d748
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "AudioChannelAgent.h"
6 #include "AudioChannelService.h"
7 #include "mozilla/Preferences.h"
8 #include "nsContentUtils.h"
9 #include "mozilla/dom/Document.h"
10 #include "nsPIDOMWindow.h"
12 using namespace mozilla::dom;
14 NS_IMPL_CYCLE_COLLECTION_CLASS(AudioChannelAgent)
16 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioChannelAgent)
17 tmp->Shutdown();
18 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
19 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
20 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
22 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioChannelAgent)
23 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
24 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
27 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioChannelAgent)
28 NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgent)
29 NS_INTERFACE_MAP_ENTRY(nsISupports)
30 NS_INTERFACE_MAP_END
32 NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioChannelAgent)
33 NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioChannelAgent)
35 AudioChannelAgent::AudioChannelAgent()
36 : mInnerWindowID(0), mIsRegToService(false) {
37 // Init service in the begining, it can help us to know whether there is any
38 // created media component via AudioChannelService::IsServiceStarted().
39 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
42 AudioChannelAgent::~AudioChannelAgent() { Shutdown(); }
44 void AudioChannelAgent::Shutdown() {
45 if (mIsRegToService) {
46 NotifyStoppedPlaying();
50 NS_IMETHODIMP
51 AudioChannelAgent::Init(mozIDOMWindow* aWindow,
52 nsIAudioChannelAgentCallback* aCallback) {
53 return InitInternal(nsPIDOMWindowInner::From(aWindow), aCallback,
54 /* useWeakRef = */ false);
57 NS_IMETHODIMP
58 AudioChannelAgent::InitWithWeakCallback(
59 mozIDOMWindow* aWindow, nsIAudioChannelAgentCallback* aCallback) {
60 return InitInternal(nsPIDOMWindowInner::From(aWindow), aCallback,
61 /* useWeakRef = */ true);
64 nsresult AudioChannelAgent::FindCorrectWindow(nsPIDOMWindowInner* aWindow) {
65 mWindow = aWindow->GetInProcessScriptableTop();
66 if (NS_WARN_IF(!mWindow)) {
67 return NS_OK;
70 // From here we do an hack for nested iframes.
71 // The system app doesn't have access to the nested iframe objects so it
72 // cannot control the volume of the agents running in nested apps. What we do
73 // here is to assign those Agents to the top scriptable window of the parent
74 // iframe (what is controlled by the system app).
75 // For doing this we go recursively back into the chain of windows until we
76 // find apps that are not the system one.
77 nsCOMPtr<nsPIDOMWindowOuter> outerParent = mWindow->GetInProcessParent();
78 if (!outerParent || outerParent == mWindow) {
79 return NS_OK;
82 nsCOMPtr<nsPIDOMWindowInner> parent = outerParent->GetCurrentInnerWindow();
83 if (!parent) {
84 return NS_OK;
87 nsCOMPtr<Document> doc = parent->GetExtantDoc();
88 if (!doc) {
89 return NS_OK;
92 if (nsContentUtils::IsChromeDoc(doc)) {
93 return NS_OK;
96 return FindCorrectWindow(parent);
99 nsresult AudioChannelAgent::InitInternal(
100 nsPIDOMWindowInner* aWindow, nsIAudioChannelAgentCallback* aCallback,
101 bool aUseWeakRef) {
102 if (NS_WARN_IF(!aWindow)) {
103 return NS_ERROR_FAILURE;
106 mInnerWindowID = aWindow->WindowID();
108 nsresult rv = FindCorrectWindow(aWindow);
109 if (NS_WARN_IF(NS_FAILED(rv))) {
110 return rv;
113 if (aUseWeakRef) {
114 mWeakCallback = do_GetWeakReference(aCallback);
115 } else {
116 mCallback = aCallback;
119 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
120 ("AudioChannelAgent, InitInternal, this = %p, "
121 "owner = %p, hasCallback = %d\n",
122 this, mWindow.get(), (!!mCallback || !!mWeakCallback)));
124 return NS_OK;
127 void AudioChannelAgent::PullInitialUpdate() {
128 RefPtr<AudioChannelService> service = AudioChannelService::Get();
129 MOZ_ASSERT(service);
130 MOZ_ASSERT(mIsRegToService);
132 AudioPlaybackConfig config = service->GetMediaConfig(mWindow);
133 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
134 ("AudioChannelAgent, PullInitialUpdate, this=%p, "
135 "mute=%s, volume=%f, suspend=%s, audioCapturing=%s\n",
136 this, config.mMuted ? "true" : "false", config.mVolume,
137 SuspendTypeToStr(config.mSuspend),
138 config.mCapturedAudio ? "true" : "false"));
139 WindowVolumeChanged(config.mVolume, config.mMuted);
140 WindowSuspendChanged(config.mSuspend);
141 WindowAudioCaptureChanged(InnerWindowID(), config.mCapturedAudio);
144 NS_IMETHODIMP
145 AudioChannelAgent::NotifyStartedPlaying(uint8_t aAudible) {
146 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
147 if (service == nullptr || mIsRegToService) {
148 return NS_ERROR_FAILURE;
151 MOZ_ASSERT(AudioChannelService::AudibleState::eNotAudible == 0 &&
152 AudioChannelService::AudibleState::eMaybeAudible == 1 &&
153 AudioChannelService::AudibleState::eAudible == 2);
154 service->RegisterAudioChannelAgent(
155 this, static_cast<AudioChannelService::AudibleState>(aAudible));
157 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
158 ("AudioChannelAgent, NotifyStartedPlaying, this = %p, audible = %s\n",
159 this,
160 AudibleStateToStr(
161 static_cast<AudioChannelService::AudibleState>(aAudible))));
163 mIsRegToService = true;
164 return NS_OK;
167 NS_IMETHODIMP
168 AudioChannelAgent::NotifyStoppedPlaying() {
169 if (!mIsRegToService) {
170 return NS_ERROR_FAILURE;
173 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
174 ("AudioChannelAgent, NotifyStoppedPlaying, this = %p\n", this));
176 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
177 if (service) {
178 service->UnregisterAudioChannelAgent(this);
181 mIsRegToService = false;
182 return NS_OK;
185 NS_IMETHODIMP
186 AudioChannelAgent::NotifyStartedAudible(uint8_t aAudible, uint32_t aReason) {
187 MOZ_LOG(
188 AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
189 ("AudioChannelAgent, NotifyStartedAudible, this = %p, "
190 "audible = %s, reason = %s\n",
191 this,
192 AudibleStateToStr(
193 static_cast<AudioChannelService::AudibleState>(aAudible)),
194 AudibleChangedReasonToStr(
195 static_cast<AudioChannelService::AudibleChangedReasons>(aReason))));
197 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
198 if (NS_WARN_IF(!service)) {
199 return NS_ERROR_FAILURE;
202 service->AudioAudibleChanged(
203 this, static_cast<AudioChannelService::AudibleState>(aAudible),
204 static_cast<AudioChannelService::AudibleChangedReasons>(aReason));
205 return NS_OK;
208 already_AddRefed<nsIAudioChannelAgentCallback>
209 AudioChannelAgent::GetCallback() {
210 nsCOMPtr<nsIAudioChannelAgentCallback> callback = mCallback;
211 if (!callback) {
212 callback = do_QueryReferent(mWeakCallback);
214 return callback.forget();
217 void AudioChannelAgent::WindowVolumeChanged(float aVolume, bool aMuted) {
218 nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
219 if (!callback) {
220 return;
223 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
224 ("AudioChannelAgent, WindowVolumeChanged, this = %p, mute = %s, "
225 "volume = %f\n",
226 this, aMuted ? "true" : "false", aVolume));
227 callback->WindowVolumeChanged(aVolume, aMuted);
230 void AudioChannelAgent::WindowSuspendChanged(nsSuspendedTypes aSuspend) {
231 nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
232 if (!callback) {
233 return;
236 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
237 ("AudioChannelAgent, WindowSuspendChanged, this = %p, "
238 "suspended = %s\n",
239 this, SuspendTypeToStr(aSuspend)));
240 callback->WindowSuspendChanged(aSuspend);
243 AudioPlaybackConfig AudioChannelAgent::GetMediaConfig() const {
244 RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
245 AudioPlaybackConfig config(1.0, false, nsISuspendedTypes::NONE_SUSPENDED);
246 if (service) {
247 config = service->GetMediaConfig(mWindow);
249 return config;
252 uint64_t AudioChannelAgent::WindowID() const {
253 return mWindow ? mWindow->WindowID() : 0;
256 uint64_t AudioChannelAgent::InnerWindowID() const { return mInnerWindowID; }
258 void AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID,
259 bool aCapture) {
260 if (aInnerWindowID != mInnerWindowID) {
261 return;
264 nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
265 if (!callback) {
266 return;
269 MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
270 ("AudioChannelAgent, WindowAudioCaptureChanged, this = %p, "
271 "capture = %d\n",
272 this, aCapture));
274 callback->WindowAudioCaptureChanged(aCapture);
277 bool AudioChannelAgent::IsWindowAudioCapturingEnabled() const {
278 return GetMediaConfig().mCapturedAudio;
281 bool AudioChannelAgent::IsPlayingStarted() const { return mIsRegToService; }