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 18const char ChromeWhispernetClient::kWhispernetProxyExtensionId[] = 19 "bpfmnplchembfbdgieamdodgaencleal"; 20 21// Public: 22 23ChromeWhispernetClient::ChromeWhispernetClient( 24 content::BrowserContext* browser_context) 25 : browser_context_(browser_context), extension_loaded_(false) { 26} 27 28ChromeWhispernetClient::~ChromeWhispernetClient() { 29} 30 31void 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 56void 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. 65void 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. 82void 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 97void 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 111void ChromeWhispernetClient::RegisterTokensCallback( 112 const TokensCallback& tokens_callback) { 113 tokens_callback_ = tokens_callback; 114} 115 116void ChromeWhispernetClient::RegisterSamplesCallback( 117 const SamplesCallback& samples_callback) { 118 samples_callback_ = samples_callback; 119} 120 121void ChromeWhispernetClient::RegisterDetectBroadcastCallback( 122 const SuccessCallback& db_callback) { 123 db_callback_ = db_callback; 124} 125 126ChromeWhispernetClient::TokensCallback 127ChromeWhispernetClient::GetTokensCallback() { 128 return tokens_callback_; 129} 130 131ChromeWhispernetClient::SamplesCallback 132ChromeWhispernetClient::GetSamplesCallback() { 133 return samples_callback_; 134} 135 136ChromeWhispernetClient::SuccessCallback 137ChromeWhispernetClient::GetDetectBroadcastCallback() { 138 return db_callback_; 139} 140 141ChromeWhispernetClient::SuccessCallback 142ChromeWhispernetClient::GetInitializedCallback() { 143 return extension_loaded_callback_; 144} 145 146// Private: 147 148// Fire an event to initialize whispernet with the given parameters. 149void 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 163void 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