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.
4
5 #include "chrome/browser/copresence/chrome_whispernet_client.h"
6
7 #include "chrome/browser/extensions/api/copresence_private/copresence_private_api.h"
8 #include "chrome/browser/extensions/component_loader.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/common/extensions/api/copresence_private.h"
11 #include "components/copresence/public/copresence_constants.h"
12 #include "content/public/browser/browser_context.h"
13 #include "extensions/browser/event_router.h"
14 #include "extensions/browser/extension_system.h"
15 #include "grit/browser_resources.h"
16
17 // static
18 const char ChromeWhispernetClient::kWhispernetProxyExtensionId[] =
19 "bpfmnplchembfbdgieamdodgaencleal";
20
21 // Public:
22
ChromeWhispernetClient(content::BrowserContext * browser_context)23 ChromeWhispernetClient::ChromeWhispernetClient(
24 content::BrowserContext* browser_context)
25 : browser_context_(browser_context), extension_loaded_(false) {
26 }
27
~ChromeWhispernetClient()28 ChromeWhispernetClient::~ChromeWhispernetClient() {
29 }
30
Initialize(const SuccessCallback & init_callback)31 void ChromeWhispernetClient::Initialize(const SuccessCallback& init_callback) {
32 DVLOG(3) << "Initializing whispernet proxy client.";
33 init_callback_ = init_callback;
34
35 extensions::ExtensionSystem* es =
36 extensions::ExtensionSystem::Get(browser_context_);
37 DCHECK(es);
38 ExtensionService* service = es->extension_service();
39 DCHECK(service);
40 extensions::ComponentLoader* loader = service->component_loader();
41 DCHECK(loader);
42
43 // This callback is cancelled in Shutdown().
44 extension_loaded_callback_ = base::Bind(
45 &ChromeWhispernetClient::OnExtensionLoaded, base::Unretained(this));
46
47 if (!loader->Exists(kWhispernetProxyExtensionId)) {
48 DVLOG(3) << "Loading Whispernet proxy.";
49 loader->Add(IDR_WHISPERNET_PROXY_MANIFEST,
50 base::FilePath(FILE_PATH_LITERAL("whispernet_proxy")));
51 } else {
52 init_callback_.Run(true);
53 }
54 }
55
Shutdown()56 void ChromeWhispernetClient::Shutdown() {
57 extension_loaded_callback_.Reset();
58 init_callback_.Reset();
59 tokens_callback_.Reset();
60 samples_callback_.Reset();
61 db_callback_.Reset();
62 }
63
64 // Fire an event to request a token encode.
EncodeToken(const std::string & token,bool audible)65 void ChromeWhispernetClient::EncodeToken(const std::string& token,
66 bool audible) {
67 DCHECK(extension_loaded_);
68 DCHECK(browser_context_);
69 DCHECK(extensions::EventRouter::Get(browser_context_));
70
71 scoped_ptr<extensions::Event> event(new extensions::Event(
72 extensions::api::copresence_private::OnEncodeTokenRequest::kEventName,
73 extensions::api::copresence_private::OnEncodeTokenRequest::Create(
74 token, audible),
75 browser_context_));
76
77 extensions::EventRouter::Get(browser_context_)
78 ->DispatchEventToExtension(kWhispernetProxyExtensionId, event.Pass());
79 }
80
81 // Fire an event to request a decode for the given samples.
DecodeSamples(const std::string & samples)82 void ChromeWhispernetClient::DecodeSamples(const std::string& samples) {
83 DCHECK(extension_loaded_);
84 DCHECK(browser_context_);
85 DCHECK(extensions::EventRouter::Get(browser_context_));
86
87 scoped_ptr<extensions::Event> event(new extensions::Event(
88 extensions::api::copresence_private::OnDecodeSamplesRequest::kEventName,
89 extensions::api::copresence_private::OnDecodeSamplesRequest::Create(
90 samples),
91 browser_context_));
92
93 extensions::EventRouter::Get(browser_context_)
94 ->DispatchEventToExtension(kWhispernetProxyExtensionId, event.Pass());
95 }
96
DetectBroadcast()97 void ChromeWhispernetClient::DetectBroadcast() {
98 DCHECK(extension_loaded_);
99 DCHECK(browser_context_);
100 DCHECK(extensions::EventRouter::Get(browser_context_));
101
102 scoped_ptr<extensions::Event> event(new extensions::Event(
103 extensions::api::copresence_private::OnDetectBroadcastRequest::kEventName,
104 make_scoped_ptr(new base::ListValue()),
105 browser_context_));
106
107 extensions::EventRouter::Get(browser_context_)
108 ->DispatchEventToExtension(kWhispernetProxyExtensionId, event.Pass());
109 }
110
RegisterTokensCallback(const TokensCallback & tokens_callback)111 void ChromeWhispernetClient::RegisterTokensCallback(
112 const TokensCallback& tokens_callback) {
113 tokens_callback_ = tokens_callback;
114 }
115
RegisterSamplesCallback(const SamplesCallback & samples_callback)116 void ChromeWhispernetClient::RegisterSamplesCallback(
117 const SamplesCallback& samples_callback) {
118 samples_callback_ = samples_callback;
119 }
120
RegisterDetectBroadcastCallback(const SuccessCallback & db_callback)121 void ChromeWhispernetClient::RegisterDetectBroadcastCallback(
122 const SuccessCallback& db_callback) {
123 db_callback_ = db_callback;
124 }
125
126 ChromeWhispernetClient::TokensCallback
GetTokensCallback()127 ChromeWhispernetClient::GetTokensCallback() {
128 return tokens_callback_;
129 }
130
131 ChromeWhispernetClient::SamplesCallback
GetSamplesCallback()132 ChromeWhispernetClient::GetSamplesCallback() {
133 return samples_callback_;
134 }
135
136 ChromeWhispernetClient::SuccessCallback
GetDetectBroadcastCallback()137 ChromeWhispernetClient::GetDetectBroadcastCallback() {
138 return db_callback_;
139 }
140
141 ChromeWhispernetClient::SuccessCallback
GetInitializedCallback()142 ChromeWhispernetClient::GetInitializedCallback() {
143 return extension_loaded_callback_;
144 }
145
146 // Private:
147
148 // Fire an event to initialize whispernet with the given parameters.
InitializeWhispernet(const extensions::api::copresence_private::AudioParameters & params)149 void ChromeWhispernetClient::InitializeWhispernet(
150 const extensions::api::copresence_private::AudioParameters& params) {
151 DCHECK(browser_context_);
152 DCHECK(extensions::EventRouter::Get(browser_context_));
153
154 scoped_ptr<extensions::Event> event(new extensions::Event(
155 extensions::api::copresence_private::OnInitialize::kEventName,
156 extensions::api::copresence_private::OnInitialize::Create(params),
157 browser_context_));
158
159 extensions::EventRouter::Get(browser_context_)
160 ->DispatchEventToExtension(kWhispernetProxyExtensionId, event.Pass());
161 }
162
OnExtensionLoaded(bool success)163 void ChromeWhispernetClient::OnExtensionLoaded(bool success) {
164 if (extension_loaded_) {
165 if (!init_callback_.is_null())
166 init_callback_.Run(success);
167 return;
168 }
169
170 // Our extension just got loaded, initialize whispernet.
171 extension_loaded_ = true;
172
173 // This will fire another OnExtensionLoaded call once the initialization is
174 // done, which means we've initialized for realz, hence call the init
175 // callback.
176
177 // At this point, we have the same parameters for record and play. This
178 // may change later though (ongoing discussion with research).
179 extensions::api::copresence_private::AudioParameters params;
180 params.play.sample_rate = copresence::kDefaultSampleRate;
181 params.play.bits_per_sample = copresence::kDefaultBitsPerSample;
182 params.play.carrier_frequency = copresence::kDefaultCarrierFrequency;
183 params.play.repetitions = copresence::kDefaultRepetitions;
184
185 params.record.sample_rate = copresence::kDefaultSampleRate;
186 params.record.bits_per_sample = copresence::kDefaultBitsPerSample;
187 params.record.carrier_frequency = copresence::kDefaultCarrierFrequency;
188 params.record.channels = copresence::kDefaultChannels;
189
190 InitializeWhispernet(params);
191 }
192