1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_
6#define CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_
7
8#include "base/memory/ref_counted.h"
9#include "base/system_monitor/system_monitor.h"
10#include "chrome/browser/extensions/chrome_extension_function.h"
11#include "chrome/common/extensions/api/webrtc_audio_private.h"
12#include "content/public/browser/render_view_host.h"
13#include "extensions/browser/browser_context_keyed_api_factory.h"
14#include "media/audio/audio_device_name.h"
15#include "url/gurl.h"
16
17namespace content {
18class ResourceContext;
19}
20
21namespace extensions {
22
23// Listens for device changes and forwards as an extension event.
24class WebrtcAudioPrivateEventService
25    : public BrowserContextKeyedAPI,
26      public base::SystemMonitor::DevicesChangedObserver {
27 public:
28  explicit WebrtcAudioPrivateEventService(content::BrowserContext* context);
29  virtual ~WebrtcAudioPrivateEventService();
30
31  // BrowserContextKeyedAPI implementation.
32  virtual void Shutdown() OVERRIDE;
33  static BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService>*
34      GetFactoryInstance();
35  static const char* service_name();
36
37  // base::SystemMonitor::DevicesChangedObserver implementation.
38  virtual void OnDevicesChanged(
39      base::SystemMonitor::DeviceType device_type) OVERRIDE;
40
41 private:
42  friend class BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService>;
43
44  void SignalEvent();
45
46  content::BrowserContext* browser_context_;
47};
48
49// Common base for WebrtcAudioPrivate functions, that provides a
50// couple of optionally-used common implementations.
51class WebrtcAudioPrivateFunction : public ChromeAsyncExtensionFunction {
52 protected:
53  WebrtcAudioPrivateFunction();
54  virtual ~WebrtcAudioPrivateFunction();
55
56 protected:
57  // Retrieves the list of output device names on the appropriate
58  // thread. Call from UI thread, callback will occur on IO thread.
59  void GetOutputDeviceNames();
60
61  // Must override this if you call GetOutputDeviceNames. Called on IO thread.
62  virtual void OnOutputDeviceNames(
63      scoped_ptr<media::AudioDeviceNames> device_names);
64
65  // Retrieve the list of AudioOutputController objects. Calls back
66  // via OnControllerList.
67  //
68  // Returns false on error, in which case it has set |error_| and the
69  // entire function should fail.
70  //
71  // Call from any thread. Callback will occur on originating thread.
72  bool GetControllerList(int tab_id);
73
74  // Must override this if you call GetControllerList.
75  virtual void OnControllerList(
76      const content::RenderViewHost::AudioOutputControllerList& list);
77
78  // Calculates a single HMAC. Call from any thread. Calls back via
79  // OnHMACCalculated on UI thread.
80  //
81  // This function, and device ID HMACs in this API in general use the
82  // calling extension's ID as the security origin. The only exception
83  // to this rule is when calculating the input device ID HMAC in
84  // getAssociatedSink, where we use the provided |securityOrigin|.
85  void CalculateHMAC(const std::string& raw_id);
86
87  // Must override this if you call CalculateHMAC.
88  virtual void OnHMACCalculated(const std::string& hmac);
89
90  // Calculates a single HMAC, using the extension ID as the security origin.
91  //
92  // Call only on IO thread.
93  std::string CalculateHMACImpl(const std::string& raw_id);
94
95  // Initializes |resource_context_|. Must be called on the UI thread,
96  // before any calls to |resource_context()|.
97  void InitResourceContext();
98
99  // Callable from any thread. Must previously have called
100  // |InitResourceContext()|.
101  content::ResourceContext* resource_context() const;
102
103 private:
104  content::ResourceContext* resource_context_;
105
106  DISALLOW_COPY_AND_ASSIGN(WebrtcAudioPrivateFunction);
107};
108
109class WebrtcAudioPrivateGetSinksFunction : public WebrtcAudioPrivateFunction {
110 protected:
111  virtual ~WebrtcAudioPrivateGetSinksFunction() {}
112
113 private:
114  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getSinks",
115                             WEBRTC_AUDIO_PRIVATE_GET_SINKS);
116
117  // Sequence of events is that we query the list of sinks on the
118  // AudioManager's thread, then calculate HMACs on the IO thread,
119  // then finish on the UI thread.
120  virtual bool RunAsync() OVERRIDE;
121  void DoQuery();
122  virtual void OnOutputDeviceNames(
123      scoped_ptr<media::AudioDeviceNames> raw_ids) OVERRIDE;
124  void DoneOnUIThread();
125};
126
127class WebrtcAudioPrivateGetActiveSinkFunction
128    : public WebrtcAudioPrivateFunction {
129 protected:
130  virtual ~WebrtcAudioPrivateGetActiveSinkFunction() {}
131
132 private:
133  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getActiveSink",
134                             WEBRTC_AUDIO_PRIVATE_GET_ACTIVE_SINK);
135
136  virtual bool RunAsync() OVERRIDE;
137  virtual void OnControllerList(
138      const content::RenderViewHost::AudioOutputControllerList&
139      controllers) OVERRIDE;
140  virtual void OnHMACCalculated(const std::string& hmac) OVERRIDE;
141};
142
143class WebrtcAudioPrivateSetActiveSinkFunction
144    : public WebrtcAudioPrivateFunction {
145 public:
146  WebrtcAudioPrivateSetActiveSinkFunction();
147
148 protected:
149  virtual ~WebrtcAudioPrivateSetActiveSinkFunction();
150
151 private:
152  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.setActiveSink",
153                             WEBRTC_AUDIO_PRIVATE_SET_ACTIVE_SINK);
154
155  virtual bool RunAsync() OVERRIDE;
156  virtual void OnControllerList(
157      const content::RenderViewHost::AudioOutputControllerList&
158      controllers) OVERRIDE;
159  virtual void OnOutputDeviceNames(
160      scoped_ptr<media::AudioDeviceNames> device_names) OVERRIDE;
161  void SwitchDone();
162  void DoneOnUIThread();
163
164  int tab_id_;
165  std::string sink_id_;
166
167  // Filled in by OnControllerList.
168  content::RenderViewHost::AudioOutputControllerList controllers_;
169
170  // Number of sink IDs we are still waiting for. Can become greater
171  // than 0 in OnControllerList, decreases on every OnSinkId call.
172  size_t num_remaining_sink_ids_;
173};
174
175class WebrtcAudioPrivateGetAssociatedSinkFunction
176    : public WebrtcAudioPrivateFunction {
177 public:
178  WebrtcAudioPrivateGetAssociatedSinkFunction();
179
180 protected:
181  virtual ~WebrtcAudioPrivateGetAssociatedSinkFunction();
182
183 private:
184  DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getAssociatedSink",
185                             WEBRTC_AUDIO_PRIVATE_GET_ASSOCIATED_SINK);
186
187  virtual bool RunAsync() OVERRIDE;
188
189  // This implementation is slightly complicated because of different
190  // thread requirements for the various functions we need to invoke.
191  //
192  // Each worker function will post a task to the appropriate thread
193  // for the next one.
194  //
195  // The sequence of events is:
196  // 1. Get the list of source devices on the device thread.
197  // 2. Given a source ID for an origin and that security origin, find
198  //    the raw source ID. This needs to happen on the IO thread since
199  //    we will be using the ResourceContext.
200  // 3. Given a raw source ID, get the raw associated sink ID on the
201  //    device thread.
202  // 4. Given the raw associated sink ID, get its HMAC on the IO thread.
203  // 5. Respond with the HMAC of the associated sink ID on the UI thread.
204
205  // Fills in |source_devices_|. Note that these are input devices,
206  // not output devices, so don't use
207  // |WebrtcAudioPrivateFunction::GetOutputDeviceNames|.
208  void GetDevicesOnDeviceThread();
209
210  // Takes the parameters of the function, retrieves the raw source
211  // device ID, or the empty string if none.
212  void GetRawSourceIDOnIOThread();
213
214  // Gets the raw sink ID for a raw source ID. Sends it to |CalculateHMAC|.
215  void GetAssociatedSinkOnDeviceThread(const std::string& raw_source_id);
216
217  // Receives the associated sink ID after its HMAC is calculated.
218  virtual void OnHMACCalculated(const std::string& hmac) OVERRIDE;
219
220  // Accessed from UI thread and device thread, but only on one at a
221  // time, no locking needed.
222  scoped_ptr<api::webrtc_audio_private::GetAssociatedSink::Params> params_;
223
224  // Audio sources (input devices). Filled in by DoWorkOnDeviceThread.
225  media::AudioDeviceNames source_devices_;
226};
227
228}  // namespace extensions
229
230#endif  // CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_
231