summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h
blob: 20370e5cd9fbac67bffbe8a6b8f4a602497396fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_

#include <stddef.h>

#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/system_monitor/system_monitor.h"
#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/webrtc_audio_private.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "media/audio/audio_device_name.h"
#include "url/gurl.h"

namespace extensions {

// Listens for device changes and forwards as an extension event.
class WebrtcAudioPrivateEventService
    : public BrowserContextKeyedAPI,
      public base::SystemMonitor::DevicesChangedObserver {
 public:
  explicit WebrtcAudioPrivateEventService(content::BrowserContext* context);
  ~WebrtcAudioPrivateEventService() override;

  // BrowserContextKeyedAPI implementation.
  void Shutdown() override;
  static BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService>*
      GetFactoryInstance();
  static const char* service_name();

  // base::SystemMonitor::DevicesChangedObserver implementation.
  void OnDevicesChanged(base::SystemMonitor::DeviceType device_type) override;

 private:
  friend class BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService>;

  void SignalEvent();

  content::BrowserContext* browser_context_;
};

// Common base for WebrtcAudioPrivate functions, that provides a
// couple of optionally-used common implementations.
class WebrtcAudioPrivateFunction : public ChromeAsyncExtensionFunction {
 protected:
  WebrtcAudioPrivateFunction();
  ~WebrtcAudioPrivateFunction() override;

 protected:
  // Retrieves the list of output device names on the appropriate
  // thread. Call from UI thread, callback will occur on IO thread.
  void GetOutputDeviceNames();

  // Must override this if you call GetOutputDeviceNames. Called on IO thread.
  virtual void OnOutputDeviceNames(
      scoped_ptr<media::AudioDeviceNames> device_names);

  // Retrieve the list of AudioOutputController objects. Calls back
  // via OnControllerList.
  //
  // Returns false on error, in which case it has set |error_| and the
  // entire function should fail.
  //
  // Call from any thread. Callback will occur on originating thread.
  bool GetControllerList(const api::webrtc_audio_private::RequestInfo& request);

  // Must override this if you call GetControllerList.
  virtual void OnControllerList(
      const content::RenderProcessHost::AudioOutputControllerList& list);

  // Calculates a single HMAC. Call from any thread. Calls back via
  // OnHMACCalculated on UI thread.
  //
  // This function, and device ID HMACs in this API in general use the
  // calling extension's ID as the security origin. The only exception
  // to this rule is when calculating the input device ID HMAC in
  // getAssociatedSink, where we use the provided |securityOrigin|.
  void CalculateHMAC(const std::string& raw_id);

  // Must override this if you call CalculateHMAC.
  virtual void OnHMACCalculated(const std::string& hmac);

  // Calculates a single HMAC, using the extension ID as the security origin.
  //
  // Call only on IO thread.
  std::string CalculateHMACImpl(const std::string& raw_id);

  // Initializes |device_id_salt_|. Must be called on the UI thread,
  // before any calls to |device_id_salt()|.
  void InitDeviceIDSalt();

  // Callable from any thread. Must previously have called
  // |InitDeviceIDSalt()|.
  const content::ResourceContext::SaltCallback& device_id_salt() const;

 private:
  content::ResourceContext::SaltCallback device_id_salt_;

  DISALLOW_COPY_AND_ASSIGN(WebrtcAudioPrivateFunction);
};

class WebrtcAudioPrivateGetSinksFunction : public WebrtcAudioPrivateFunction {
 protected:
  ~WebrtcAudioPrivateGetSinksFunction() override {}

 private:
  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getSinks",
                             WEBRTC_AUDIO_PRIVATE_GET_SINKS);

  // Sequence of events is that we query the list of sinks on the
  // AudioManager's thread, then calculate HMACs on the IO thread,
  // then finish on the UI thread.
  bool RunAsync() override;
  void DoQuery();
  void OnOutputDeviceNames(
      scoped_ptr<media::AudioDeviceNames> raw_ids) override;
  void DoneOnUIThread();
};

class WebrtcAudioPrivateGetActiveSinkFunction
    : public WebrtcAudioPrivateFunction {
 protected:
  ~WebrtcAudioPrivateGetActiveSinkFunction() override {}

 private:
  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getActiveSink",
                             WEBRTC_AUDIO_PRIVATE_GET_ACTIVE_SINK);

  bool RunAsync() override;
  void OnControllerList(
      const content::RenderProcessHost::AudioOutputControllerList& controllers)
      override;
  void OnHMACCalculated(const std::string& hmac) override;
};

class WebrtcAudioPrivateSetActiveSinkFunction
    : public WebrtcAudioPrivateFunction {
 public:
  WebrtcAudioPrivateSetActiveSinkFunction();

 protected:
  ~WebrtcAudioPrivateSetActiveSinkFunction() override;

 private:
  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.setActiveSink",
                             WEBRTC_AUDIO_PRIVATE_SET_ACTIVE_SINK);

  bool RunAsync() override;
  void OnControllerList(
      const content::RenderProcessHost::AudioOutputControllerList& controllers)
      override;
  void OnOutputDeviceNames(
      scoped_ptr<media::AudioDeviceNames> device_names) override;
  void SwitchDone();
  void DoneOnUIThread();

  api::webrtc_audio_private::RequestInfo request_info_;
  std::string sink_id_;

  // Filled in by OnControllerList.
  content::RenderProcessHost::AudioOutputControllerList controllers_;

  // Number of sink IDs we are still waiting for. Can become greater
  // than 0 in OnControllerList, decreases on every OnSinkId call.
  size_t num_remaining_sink_ids_;
};

class WebrtcAudioPrivateGetAssociatedSinkFunction
    : public WebrtcAudioPrivateFunction {
 public:
  WebrtcAudioPrivateGetAssociatedSinkFunction();

 protected:
  ~WebrtcAudioPrivateGetAssociatedSinkFunction() override;

 private:
  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getAssociatedSink",
                             WEBRTC_AUDIO_PRIVATE_GET_ASSOCIATED_SINK);

  bool RunAsync() override;

  // This implementation is slightly complicated because of different
  // thread requirements for the various functions we need to invoke.
  //
  // Each worker function will post a task to the appropriate thread
  // for the next one.
  //
  // The sequence of events is:
  // 1. Get the list of source devices on the device thread.
  // 2. Given a source ID for an origin and that security origin, find
  //    the raw source ID. This needs to happen on the IO thread since
  //    we will be using the ResourceContext.
  // 3. Given a raw source ID, get the raw associated sink ID on the
  //    device thread.
  // 4. Given the raw associated sink ID, get its HMAC on the IO thread.
  // 5. Respond with the HMAC of the associated sink ID on the UI thread.

  // Fills in |source_devices_|. Note that these are input devices,
  // not output devices, so don't use
  // |WebrtcAudioPrivateFunction::GetOutputDeviceNames|.
  void GetDevicesOnDeviceThread();

  // Takes the parameters of the function, retrieves the raw source
  // device ID, or the empty string if none.
  void GetRawSourceIDOnIOThread();

  // Gets the raw sink ID for a raw source ID. Sends it to |CalculateHMAC|.
  void GetAssociatedSinkOnDeviceThread(const std::string& raw_source_id);

  // Receives the associated sink ID after its HMAC is calculated.
  void OnHMACCalculated(const std::string& hmac) override;

  // Accessed from UI thread and device thread, but only on one at a
  // time, no locking needed.
  scoped_ptr<api::webrtc_audio_private::GetAssociatedSink::Params> params_;

  // Audio sources (input devices). Filled in by DoWorkOnDeviceThread.
  media::AudioDeviceNames source_devices_;
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_