Remove aura enum from DesktopMediaID to fix desktop mirroring audio (CrOS).
[chromium-blink-merge.git] / chrome / browser / copresence / chrome_whispernet_client.cc
blob52ae76cbbf99733eace1362a25af3bc5f089a5e5
1 // Copyright 2014 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.
5 #include "chrome/browser/copresence/chrome_whispernet_client.h"
7 #include "base/stl_util.h"
8 #include "chrome/browser/copresence/chrome_whispernet_config.h"
9 #include "chrome/browser/extensions/api/copresence_private/copresence_private_api.h"
10 #include "chrome/browser/extensions/component_loader.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/common/extensions/api/copresence_private.h"
13 #include "content/public/browser/browser_context.h"
14 #include "extensions/browser/event_router.h"
15 #include "extensions/browser/extension_system.h"
16 #include "grit/browser_resources.h"
17 #include "media/audio/audio_manager.h"
18 #include "media/audio/audio_manager_base.h"
19 #include "media/audio/audio_parameters.h"
21 using audio_modem::AUDIBLE;
22 using audio_modem::AudioType;
23 using audio_modem::BOTH;
24 using audio_modem::INAUDIBLE;
25 using audio_modem::SamplesCallback;
26 using audio_modem::SuccessCallback;
27 using audio_modem::TokensCallback;
28 using audio_modem::TokenParameters;
30 using extensions::api::copresence_private::AudioParameters;
31 using extensions::api::copresence_private::DecodeSamplesParameters;
32 using extensions::api::copresence_private::EncodeTokenParameters;
33 using ApiTokenParams = extensions::api::copresence_private::TokenParameters;
35 namespace OnConfigAudio =
36 extensions::api::copresence_private::OnConfigAudio;
37 namespace OnDecodeSamplesRequest =
38 extensions::api::copresence_private::OnDecodeSamplesRequest;
39 namespace OnEncodeTokenRequest =
40 extensions::api::copresence_private::OnEncodeTokenRequest;
42 using extensions::Event;
44 namespace {
46 AudioParamData GetDefaultAudioConfig() {
47 media::AudioParameters params =
48 media::AudioManager::Get()->GetInputStreamParameters(
49 media::AudioManagerBase::kDefaultDeviceId);
51 AudioParamData config_data = {};
53 config_data.audio_dtmf.coder_sample_rate =
54 config_data.audio_dsss.coder_sample_rate =
55 audio_modem::kDefaultSampleRate;
57 config_data.audio_dtmf.recording_sample_rate =
58 config_data.audio_dsss.recording_sample_rate = params.sample_rate();
60 config_data.audio_dtmf.num_repetitions_to_play =
61 config_data.audio_dsss.num_repetitions_to_play =
62 audio_modem::kDefaultRepetitions;
64 config_data.audio_dsss.upsampling_factor = audio_modem::kDefaultBitsPerSample;
65 config_data.audio_dsss.desired_carrier_frequency =
66 audio_modem::kDefaultCarrierFrequency;
68 config_data.recording_channels = params.channels();
70 return config_data;
73 // ApiTokenParams is not copyable, so we must take it as an output argument.
74 // TODO(ckehoe): Pass protos to Whispernet to avoid all these conversions.
75 void ConvertTokenParams(const TokenParameters& in, ApiTokenParams* out) {
76 out->length = in.length;
77 out->crc = in.crc;
78 out->parity = in.parity;
81 } // namespace
83 // static
84 const char ChromeWhispernetClient::kWhispernetProxyExtensionId[] =
85 "bpfmnplchembfbdgieamdodgaencleal";
88 // Public functions.
90 ChromeWhispernetClient::ChromeWhispernetClient(
91 content::BrowserContext* browser_context)
92 : browser_context_(browser_context),
93 event_router_(extensions::EventRouter::Get(browser_context)),
94 extension_loaded_(false) {
95 DCHECK(browser_context_);
98 ChromeWhispernetClient::~ChromeWhispernetClient() {}
100 void ChromeWhispernetClient::Initialize(
101 const SuccessCallback& init_callback) {
102 DVLOG(3) << "Initializing whispernet proxy client.";
104 DCHECK(!init_callback.is_null());
105 init_callback_ = init_callback;
107 ExtensionService* extension_service =
108 extensions::ExtensionSystem::Get(browser_context_)->extension_service();
109 CHECK(extension_service);
111 extensions::ComponentLoader* loader = extension_service->component_loader();
112 CHECK(loader);
113 if (!loader->Exists(kWhispernetProxyExtensionId)) {
114 DVLOG(3) << "Loading Whispernet proxy.";
115 loader->Add(IDR_WHISPERNET_PROXY_MANIFEST,
116 base::FilePath(FILE_PATH_LITERAL("whispernet_proxy")));
119 client_id_ = extensions::CopresencePrivateService::GetFactoryInstance()
120 ->Get(browser_context_)->RegisterWhispernetClient(this);
121 AudioConfiguration(GetDefaultAudioConfig());
124 void ChromeWhispernetClient::EncodeToken(
125 const std::string& token_str,
126 AudioType type,
127 const TokenParameters token_params[2]) {
128 DCHECK(type == AUDIBLE || type == INAUDIBLE);
130 EncodeTokenParameters params;
131 params.token.token = token_str;
132 params.token.audible = (type == AUDIBLE);
133 ConvertTokenParams(token_params[type], &params.token_params);
135 SendEventIfLoaded(make_scoped_ptr(new Event(
136 extensions::events::COPRESENCE_PRIVATE_ON_ENCODE_TOKEN_REQUEST,
137 OnEncodeTokenRequest::kEventName,
138 OnEncodeTokenRequest::Create(client_id_, params), browser_context_)));
141 void ChromeWhispernetClient::DecodeSamples(
142 AudioType type,
143 const std::string& samples,
144 const TokenParameters token_params[2]) {
145 DecodeSamplesParameters params;
146 params.samples.assign(samples.begin(), samples.end());
147 params.decode_audible = (type == AUDIBLE || type == BOTH);
148 params.decode_inaudible = (type == INAUDIBLE || type == BOTH);
149 ConvertTokenParams(token_params[AUDIBLE], &params.audible_token_params);
150 ConvertTokenParams(token_params[INAUDIBLE], &params.inaudible_token_params);
152 SendEventIfLoaded(make_scoped_ptr(new Event(
153 extensions::events::COPRESENCE_PRIVATE_ON_DECODE_SAMPLES_REQUEST,
154 OnDecodeSamplesRequest::kEventName,
155 OnDecodeSamplesRequest::Create(client_id_, params), browser_context_)));
158 void ChromeWhispernetClient::RegisterTokensCallback(
159 const TokensCallback& tokens_callback) {
160 tokens_callback_ = tokens_callback;
163 void ChromeWhispernetClient::RegisterSamplesCallback(
164 const SamplesCallback& samples_callback) {
165 samples_callback_ = samples_callback;
168 TokensCallback ChromeWhispernetClient::GetTokensCallback() {
169 return tokens_callback_;
172 SamplesCallback ChromeWhispernetClient::GetSamplesCallback() {
173 return samples_callback_;
176 SuccessCallback ChromeWhispernetClient::GetInitializedCallback() {
177 return base::Bind(&ChromeWhispernetClient::OnExtensionLoaded,
178 base::Unretained(this));
182 // Private functions.
184 void ChromeWhispernetClient::AudioConfiguration(const AudioParamData& params) {
185 AudioParameters audio_params;
187 // We serialize AudioConfigData to a string and send it to the whispernet
188 // nacl wrapper.
189 const size_t params_size = sizeof(params);
190 audio_params.param_data.resize(params_size);
191 memcpy(vector_as_array(&audio_params.param_data), &params, params_size);
193 DVLOG(3) << "Configuring audio for client " << client_id_;
194 SendEventIfLoaded(make_scoped_ptr(new Event(
195 extensions::events::COPRESENCE_PRIVATE_ON_CONFIG_AUDIO,
196 OnConfigAudio::kEventName,
197 OnConfigAudio::Create(client_id_, audio_params), browser_context_)));
200 void ChromeWhispernetClient::SendEventIfLoaded(
201 scoped_ptr<extensions::Event> event) {
202 DCHECK(event_router_);
204 if (extension_loaded_) {
205 event_router_->DispatchEventToExtension(kWhispernetProxyExtensionId,
206 event.Pass());
207 } else {
208 DVLOG(2) << "Queueing event " << event->event_name
209 << " for client " << client_id_;
210 queued_events_.push_back(event.release());
214 void ChromeWhispernetClient::OnExtensionLoaded(bool success) {
215 DCHECK(!init_callback_.is_null());
216 init_callback_.Run(success);
218 DVLOG(3) << "Sending " << queued_events_.size()
219 << " queued requests to whispernet from client "
220 << client_id_;
222 // In this loop, ownership of each Event is passed to a scoped_ptr instead.
223 // Thus we can just discard the pointers at the end.
224 DCHECK(event_router_);
225 for (Event* event : queued_events_) {
226 event_router_->DispatchEventToExtension(kWhispernetProxyExtensionId,
227 make_scoped_ptr(event));
229 queued_events_.weak_clear();
231 extension_loaded_ = true;