Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/AudioChannelService.h
Line
Count
Source (jump to first uncovered line)
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 file,
5
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_dom_audiochannelservice_h__
8
#define mozilla_dom_audiochannelservice_h__
9
10
#include "nsAutoPtr.h"
11
#include "nsIObserver.h"
12
#include "nsTObserverArray.h"
13
#include "nsTArray.h"
14
15
#include "AudioChannelAgent.h"
16
#include "nsAttrValue.h"
17
#include "mozilla/Logging.h"
18
19
#include <functional>
20
21
class nsPIDOMWindowOuter;
22
struct PRLogModuleInfo;
23
24
namespace mozilla {
25
namespace dom {
26
27
class AudioPlaybackConfig
28
{
29
public:
30
  AudioPlaybackConfig()
31
    : mVolume(1.0)
32
    , mMuted(false)
33
    , mSuspend(nsISuspendedTypes::NONE_SUSPENDED)
34
    , mNumberOfAgents(0)
35
0
  {}
36
37
  AudioPlaybackConfig(float aVolume, bool aMuted, uint32_t aSuspended)
38
    : mVolume(aVolume)
39
    , mMuted(aMuted)
40
    , mSuspend(aSuspended)
41
    , mNumberOfAgents(0)
42
  {}
43
44
  void SetConfig(float aVolume, bool aMuted, uint32_t aSuspended)
45
  {
46
    mVolume = aVolume;
47
    mMuted = aMuted;
48
    mSuspend = aSuspended;
49
  }
50
51
  float mVolume;
52
  bool mMuted;
53
  uint32_t mSuspend;
54
  uint32_t mNumberOfAgents;
55
};
56
57
class AudioChannelService final : public nsIObserver
58
{
59
public:
60
  NS_DECL_ISUPPORTS
61
  NS_DECL_NSIOBSERVER
62
63
  /**
64
   * eNotAudible : agent is not audible
65
   * eMaybeAudible : agent is not audible now, but it might be audible later
66
   * eAudible : agent is audible now
67
   */
68
  enum AudibleState : uint8_t {
69
    eNotAudible = 0,
70
    eMaybeAudible = 1,
71
    eAudible = 2
72
  };
73
74
  enum AudioCaptureState : bool {
75
    eCapturing = true,
76
    eNotCapturing = false
77
  };
78
79
  enum AudibleChangedReasons : uint32_t {
80
    eVolumeChanged = 0,
81
    eDataAudibleChanged = 1,
82
    ePauseStateChanged = 2
83
  };
84
85
  /**
86
   * Returns the AudioChannelServce singleton.
87
   * If AudioChannelService doesn't exist, create and return new one.
88
   * Only to be called from main thread.
89
   */
90
  static already_AddRefed<AudioChannelService> GetOrCreate();
91
92
  /**
93
   * Returns the AudioChannelService singleton if one exists.
94
   * If AudioChannelService doesn't exist, returns null.
95
   */
96
  static already_AddRefed<AudioChannelService> Get();
97
98
  static LogModule* GetAudioChannelLog();
99
100
  static bool IsEnableAudioCompeting();
101
102
  /**
103
   * Any audio channel agent that starts playing should register itself to
104
   * this service, sharing the AudioChannel.
105
   */
106
  void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
107
                                 AudibleState aAudible);
108
109
  /**
110
   * Any audio channel agent that stops playing should unregister itself to
111
   * this service.
112
   */
113
  void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
114
115
  /**
116
   * Return the state to indicate this audioChannel for his window should keep
117
   * playing/muted/suspended.
118
   */
119
  AudioPlaybackConfig GetMediaConfig(nsPIDOMWindowOuter* aWindow) const;
120
121
  /**
122
   * Called this method when the audible state of the audio playback changed,
123
   * it would dispatch the playback event to observers which want to know the
124
   * actual audible state of the window.
125
   */
126
  void AudioAudibleChanged(AudioChannelAgent* aAgent,
127
                           AudibleState aAudible,
128
                           AudibleChangedReasons aReason);
129
130
  bool IsWindowActive(nsPIDOMWindowOuter* aWindow);
131
132
  void RefreshAgentsVolume(nsPIDOMWindowOuter* aWindow);
133
  void RefreshAgentsSuspend(nsPIDOMWindowOuter* aWindow,
134
                            nsSuspendedTypes aSuspend);
135
136
  // This method needs to know the inner window that wants to capture audio. We
137
  // group agents per top outer window, but we can have multiple innerWindow per
138
  // top outerWindow (subiframes, etc.) and we have to identify all the agents
139
  // just for a particular innerWindow.
140
  void SetWindowAudioCaptured(nsPIDOMWindowOuter* aWindow,
141
                              uint64_t aInnerWindowID,
142
                              bool aCapture);
143
144
  void NotifyMediaResumedFromBlock(nsPIDOMWindowOuter* aWindow);
145
146
private:
147
  AudioChannelService();
148
  ~AudioChannelService();
149
150
  void RefreshAgents(nsPIDOMWindowOuter* aWindow,
151
                     const std::function<void(AudioChannelAgent*)>& aFunc);
152
153
  static void CreateServiceIfNeeded();
154
155
  /**
156
   * Shutdown the singleton.
157
   */
158
  static void Shutdown();
159
160
  void RefreshAgentsAudioFocusChanged(AudioChannelAgent* aAgent);
161
162
  class AudioChannelWindow final
163
  {
164
  public:
165
    explicit AudioChannelWindow(uint64_t aWindowID)
166
      : mWindowID(aWindowID)
167
      , mIsAudioCaptured(false)
168
      , mOwningAudioFocus(!AudioChannelService::IsEnableAudioCompeting())
169
      , mShouldSendActiveMediaBlockStopEvent(false)
170
    {}
171
172
    void AudioFocusChanged(AudioChannelAgent* aNewPlayingAgent);
173
    void AudioAudibleChanged(AudioChannelAgent* aAgent,
174
                             AudibleState aAudible,
175
                             AudibleChangedReasons aReason);
176
177
    void AppendAgent(AudioChannelAgent* aAgent, AudibleState aAudible);
178
    void RemoveAgent(AudioChannelAgent* aAgent);
179
180
    void NotifyMediaBlockStop(nsPIDOMWindowOuter* aWindow);
181
182
    uint64_t mWindowID;
183
    bool mIsAudioCaptured;
184
    AudioPlaybackConfig mConfig;
185
186
    // Raw pointer because the AudioChannelAgent must unregister itself.
187
    nsTObserverArray<AudioChannelAgent*> mAgents;
188
    nsTObserverArray<AudioChannelAgent*> mAudibleAgents;
189
190
    // Owning audio focus when the window starts playing audible sound, and
191
    // lose audio focus when other windows starts playing.
192
    bool mOwningAudioFocus;
193
194
    // If we've dispatched "activeMediaBlockStart" event, we must dispatch
195
    // another event "activeMediablockStop" when the window is resumed from
196
    // suspend-block.
197
    bool mShouldSendActiveMediaBlockStopEvent;
198
  private:
199
    void AudioCapturedChanged(AudioChannelAgent* aAgent,
200
                              AudioCaptureState aCapture);
201
202
    void AppendAudibleAgentIfNotContained(AudioChannelAgent* aAgent,
203
                                          AudibleChangedReasons aReason);
204
    void RemoveAudibleAgentIfContained(AudioChannelAgent* aAgent,
205
                                       AudibleChangedReasons aReason);
206
207
    void AppendAgentAndIncreaseAgentsNum(AudioChannelAgent* aAgent);
208
    void RemoveAgentAndReduceAgentsNum(AudioChannelAgent* aAgent);
209
210
    bool IsFirstAudibleAgent() const;
211
    bool IsLastAudibleAgent() const;
212
213
    void NotifyAudioAudibleChanged(nsPIDOMWindowOuter* aWindow,
214
                                   AudibleState aAudible,
215
                                   AudibleChangedReasons aReason);
216
217
    void NotifyChannelActive(uint64_t aWindowID, bool aActive);
218
    void MaybeNotifyMediaBlockStart(AudioChannelAgent* aAgent);
219
220
    void RequestAudioFocus(AudioChannelAgent* aAgent);
221
222
    // We need to do audio competing only when the new incoming agent started.
223
    void NotifyAudioCompetingChanged(AudioChannelAgent* aAgent);
224
225
    uint32_t GetCompetingBehavior(AudioChannelAgent* aAgent) const;
226
    bool IsAgentInvolvingInAudioCompeting(AudioChannelAgent* aAgent) const;
227
    bool IsAudioCompetingInSameTab() const;
228
    bool IsContainingPlayingAgent(AudioChannelAgent* aAgent) const;
229
230
    bool IsInactiveWindow() const;
231
  };
232
233
  AudioChannelWindow*
234
  GetOrCreateWindowData(nsPIDOMWindowOuter* aWindow);
235
236
  AudioChannelWindow*
237
  GetWindowData(uint64_t aWindowID) const;
238
239
  nsTObserverArray<nsAutoPtr<AudioChannelWindow>> mWindows;
240
};
241
242
const char* SuspendTypeToStr(const nsSuspendedTypes& aSuspend);
243
const char* AudibleStateToStr(const AudioChannelService::AudibleState& aAudible);
244
const char* AudibleChangedReasonToStr(const AudioChannelService::AudibleChangedReasons& aReason);
245
246
} // namespace dom
247
} // namespace mozilla
248
249
#endif