| Index: chrome/browser/extensions/api/audio_modem/audio_modem_api.cc
|
| diff --git a/chrome/browser/extensions/api/audio_modem/audio_modem_api.cc b/chrome/browser/extensions/api/audio_modem/audio_modem_api.cc
|
| deleted file mode 100644
|
| index 65a90d59fe533ea049d6366b0f10095dfdcb6acd..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/extensions/api/audio_modem/audio_modem_api.cc
|
| +++ /dev/null
|
| @@ -1,366 +0,0 @@
|
| -// Copyright 2015 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.
|
| -
|
| -#include "chrome/browser/extensions/api/audio_modem/audio_modem_api.h"
|
| -
|
| -#include <stdint.h>
|
| -
|
| -#include <map>
|
| -#include <memory>
|
| -#include <string>
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/base64.h"
|
| -#include "base/bind.h"
|
| -#include "base/guid.h"
|
| -#include "base/lazy_instance.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/timer/timer.h"
|
| -#include "chrome/browser/copresence/chrome_whispernet_client.h"
|
| -#include "chrome/common/extensions/api/audio_modem.h"
|
| -#include "extensions/browser/event_router.h"
|
| -
|
| -// TODO(ckehoe): Implement transmit fail checking.
|
| -
|
| -namespace extensions {
|
| -
|
| -using api::audio_modem::AUDIOBAND_AUDIBLE;
|
| -using api::audio_modem::AUDIOBAND_INAUDIBLE;
|
| -using api::audio_modem::Audioband;
|
| -using api::audio_modem::STATUS_CODERERROR;
|
| -using api::audio_modem::STATUS_INUSE;
|
| -using api::audio_modem::STATUS_INVALIDREQUEST;
|
| -using api::audio_modem::STATUS_SUCCESS;
|
| -using api::audio_modem::ReceivedToken;
|
| -using api::audio_modem::RequestParams;
|
| -using api::audio_modem::Status;
|
| -
|
| -namespace Transmit = api::audio_modem::Transmit;
|
| -namespace StopTransmit = api::audio_modem::StopTransmit;
|
| -namespace Receive = api::audio_modem::Receive;
|
| -namespace StopReceive = api::audio_modem::StopReceive;
|
| -namespace OnReceived = api::audio_modem::OnReceived;
|
| -
|
| -using audio_modem::AUDIBLE;
|
| -using audio_modem::AudioToken;
|
| -using audio_modem::AudioType;
|
| -using audio_modem::INAUDIBLE;
|
| -using audio_modem::TokenParameters;
|
| -
|
| -namespace {
|
| -
|
| -const char kInitFailedError[] = "The audio modem is not available. "
|
| - "Failed to initialize the token encoder/decoder.";
|
| -const char kInvalidTokenLengthError[] =
|
| - "The token length must be greater than zero.";
|
| -const char kIncorrectTokenLengthError[] =
|
| - "The token provided did not match the declared token length.";
|
| -const char kInvalidTimeoutError[] =
|
| - "Transmit and receive timeouts must be greater than zero.";
|
| -
|
| -const int kMaxTransmitTimeout = 10 * 60 * 1000; // 10 minutes
|
| -const int kMaxReceiveTimeout = 60 * 60 * 1000; // 1 hour
|
| -
|
| -base::LazyInstance<BrowserContextKeyedAPIFactory<AudioModemAPI>>
|
| - g_factory = LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -AudioType AudioTypeForBand(Audioband band) {
|
| - switch (band) {
|
| - case AUDIOBAND_AUDIBLE:
|
| - return AUDIBLE;
|
| - case AUDIOBAND_INAUDIBLE:
|
| - return INAUDIBLE;
|
| - default:
|
| - NOTREACHED();
|
| - return audio_modem::AUDIO_TYPE_UNKNOWN;
|
| - }
|
| -}
|
| -
|
| -TokenParameters TokenParamsForEncoding(
|
| - const api::audio_modem::TokenEncoding& encoding) {
|
| - return TokenParameters(encoding.token_length,
|
| - encoding.crc ? *encoding.crc : false,
|
| - encoding.parity ? *encoding.parity : true);
|
| -}
|
| -
|
| -const std::string DecodeBase64Token(std::string encoded_token) {
|
| - // Make sure the token is padded correctly.
|
| - while (encoded_token.size() % 4 > 0)
|
| - encoded_token += "=";
|
| -
|
| - // Decode and return the token.
|
| - std::string raw_token;
|
| - bool decode_success = base::Base64Decode(encoded_token, &raw_token);
|
| - DCHECK(decode_success);
|
| - return raw_token;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -
|
| -// Public functions.
|
| -
|
| -AudioModemAPI::AudioModemAPI(content::BrowserContext* context)
|
| - : AudioModemAPI(context,
|
| - base::WrapUnique(new ChromeWhispernetClient(context)),
|
| - audio_modem::Modem::Create()) {}
|
| -
|
| -AudioModemAPI::AudioModemAPI(
|
| - content::BrowserContext* context,
|
| - std::unique_ptr<audio_modem::WhispernetClient> whispernet_client,
|
| - std::unique_ptr<audio_modem::Modem> modem)
|
| - : browser_context_(context),
|
| - whispernet_client_(std::move(whispernet_client)),
|
| - modem_(std::move(modem)),
|
| - init_failed_(false) {
|
| - // We own these objects, so these callbacks will not outlive us.
|
| - whispernet_client_->Initialize(
|
| - base::Bind(&AudioModemAPI::WhispernetInitComplete,
|
| - base::Unretained(this)));
|
| - modem_->Initialize(whispernet_client_.get(),
|
| - base::Bind(&AudioModemAPI::TokensReceived,
|
| - base::Unretained(this)));
|
| -}
|
| -
|
| -AudioModemAPI::~AudioModemAPI() {
|
| - for (const auto& timer_entry : receive_timers_[0])
|
| - delete timer_entry.second;
|
| - for (const auto& timer_entry : receive_timers_[1])
|
| - delete timer_entry.second;
|
| -}
|
| -
|
| -Status AudioModemAPI::StartTransmit(const std::string& app_id,
|
| - const RequestParams& params,
|
| - const std::string& token) {
|
| - AudioType audio_type = AudioTypeForBand(params.band);
|
| - if (transmitters_[audio_type].empty())
|
| - transmitters_[audio_type] = app_id;
|
| - else if (transmitters_[audio_type] != app_id)
|
| - return STATUS_INUSE;
|
| -
|
| - DVLOG(3) << "Starting transmit for app " << app_id;
|
| -
|
| - std::string encoded_token;
|
| - base::Base64Encode(token, &encoded_token);
|
| - base::RemoveChars(encoded_token, "=", &encoded_token);
|
| -
|
| - modem_->SetTokenParams(audio_type, TokenParamsForEncoding(params.encoding));
|
| - modem_->SetToken(audio_type, encoded_token);
|
| - modem_->StartPlaying(audio_type);
|
| -
|
| - transmit_timers_[audio_type].Start(
|
| - FROM_HERE,
|
| - base::TimeDelta::FromMilliseconds(params.timeout_millis),
|
| - base::Bind(base::IgnoreResult(&AudioModemAPI::StopTransmit),
|
| - base::Unretained(this),
|
| - app_id,
|
| - audio_type));
|
| - return STATUS_SUCCESS;
|
| -}
|
| -
|
| -Status AudioModemAPI::StopTransmit(const std::string& app_id,
|
| - AudioType audio_type) {
|
| - if (transmitters_[audio_type] != app_id)
|
| - return STATUS_INVALIDREQUEST;
|
| -
|
| - DVLOG(3) << "Stopping transmit for app " << app_id;
|
| - transmitters_[audio_type].clear();
|
| - modem_->StopPlaying(audio_type);
|
| - return STATUS_SUCCESS;
|
| -}
|
| -
|
| -void AudioModemAPI::StartReceive(const std::string& app_id,
|
| - const RequestParams& params) {
|
| - DVLOG(3) << "Starting receive for app " << app_id;
|
| -
|
| - AudioType audio_type = AudioTypeForBand(params.band);
|
| - modem_->SetTokenParams(audio_type, TokenParamsForEncoding(params.encoding));
|
| - modem_->StartRecording(audio_type);
|
| -
|
| - if (receive_timers_[audio_type].count(app_id) == 0)
|
| - receive_timers_[audio_type][app_id] = new base::OneShotTimer;
|
| - DCHECK(receive_timers_[audio_type][app_id]);
|
| - receive_timers_[audio_type][app_id]->Start(
|
| - FROM_HERE,
|
| - base::TimeDelta::FromMilliseconds(params.timeout_millis),
|
| - base::Bind(base::IgnoreResult(&AudioModemAPI::StopReceive),
|
| - base::Unretained(this),
|
| - app_id,
|
| - audio_type));
|
| -}
|
| -
|
| -Status AudioModemAPI::StopReceive(const std::string& app_id,
|
| - AudioType audio_type) {
|
| - if (receive_timers_[audio_type].count(app_id) == 0)
|
| - return STATUS_INVALIDREQUEST;
|
| -
|
| - DCHECK(receive_timers_[audio_type][app_id]);
|
| - delete receive_timers_[audio_type][app_id];
|
| - receive_timers_[audio_type].erase(app_id);
|
| -
|
| - DVLOG(3) << "Stopping receive for app " << app_id;
|
| - if (receive_timers_[audio_type].empty())
|
| - modem_->StopRecording(audio_type);
|
| - return STATUS_SUCCESS;
|
| -}
|
| -
|
| -// static
|
| -BrowserContextKeyedAPIFactory<AudioModemAPI>*
|
| -AudioModemAPI::GetFactoryInstance() {
|
| - return g_factory.Pointer();
|
| -}
|
| -
|
| -
|
| -// Private functions.
|
| -
|
| -void AudioModemAPI::WhispernetInitComplete(bool success) {
|
| - if (success) {
|
| - VLOG(2) << "Whispernet initialized successfully.";
|
| - } else {
|
| - LOG(ERROR) << "Failed to initialize Whispernet!";
|
| - init_failed_ = true;
|
| - }
|
| -}
|
| -
|
| -void AudioModemAPI::TokensReceived(const std::vector<AudioToken>& tokens) {
|
| - // Distribute the tokens to the appropriate app(s).
|
| - std::list<ReceivedToken> all_tokens;
|
| - std::map<std::string, std::vector<ReceivedToken*>> tokens_by_app;
|
| - for (const AudioToken& token : tokens) {
|
| - ReceivedToken api_token;
|
| - const std::string& raw_token = DecodeBase64Token(token.token);
|
| - api_token.token.assign(raw_token.c_str(),
|
| - raw_token.c_str() + raw_token.size());
|
| - api_token.band = token.audible ? AUDIOBAND_AUDIBLE : AUDIOBAND_INAUDIBLE;
|
| - all_tokens.push_back(std::move(api_token));
|
| - for (const auto& receiver :
|
| - receive_timers_[token.audible ? AUDIBLE : INAUDIBLE]) {
|
| - tokens_by_app[receiver.first].push_back(&all_tokens.back());
|
| - }
|
| - }
|
| -
|
| - // Send events to the appropriate app(s).
|
| - for (const auto& app_entry : tokens_by_app) {
|
| - const std::string& app_id = app_entry.first;
|
| - const auto& app_tokens = app_entry.second;
|
| - if (app_id.empty())
|
| - continue;
|
| -
|
| - // Construct the event arguments by hand because a given token can be
|
| - // present for multiple listeners, so constructing a
|
| - // std::vector<ReceivedToken> for each is inefficient.
|
| - std::unique_ptr<base::ListValue> tokens_value(new base::ListValue());
|
| - for (const ReceivedToken* token : app_tokens)
|
| - tokens_value->Append(token->ToValue());
|
| - std::unique_ptr<base::ListValue> args(new base::ListValue());
|
| - args->Append(std::move(tokens_value));
|
| -
|
| - EventRouter::Get(browser_context_)
|
| - ->DispatchEventToExtension(
|
| - app_id, base::WrapUnique(new Event(events::AUDIO_MODEM_ON_RECEIVED,
|
| - OnReceived::kEventName,
|
| - std::move(args))));
|
| - }
|
| -}
|
| -
|
| -
|
| -// Functions outside the API scope.
|
| -
|
| -template <>
|
| -void
|
| -BrowserContextKeyedAPIFactory<AudioModemAPI>::DeclareFactoryDependencies() {
|
| - DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
|
| -}
|
| -
|
| -ExtensionFunction::ResponseAction AudioModemTransmitFunction::Run() {
|
| - std::unique_ptr<Transmit::Params> params(Transmit::Params::Create(*args_));
|
| - EXTENSION_FUNCTION_VALIDATE(params.get());
|
| - AudioModemAPI* api =
|
| - AudioModemAPI::GetFactoryInstance()->Get(browser_context());
|
| - if (api->init_failed()) {
|
| - return RespondNow(ErrorWithArguments(
|
| - Transmit::Results::Create(STATUS_CODERERROR),
|
| - kInitFailedError));
|
| - }
|
| -
|
| - // Check the token length.
|
| - int token_length = params->params.encoding.token_length;
|
| - if (token_length <= 0) {
|
| - return RespondNow(ErrorWithArguments(
|
| - Transmit::Results::Create(STATUS_INVALIDREQUEST),
|
| - kInvalidTokenLengthError));
|
| - }
|
| - const char* token = params->token.data();
|
| - std::string token_str(token, params->token.size());
|
| - if (static_cast<int>(token_str.size()) != token_length) {
|
| - return RespondNow(ErrorWithArguments(
|
| - Transmit::Results::Create(STATUS_INVALIDREQUEST),
|
| - kIncorrectTokenLengthError));
|
| - }
|
| -
|
| - // Check the timeout.
|
| - int64_t timeout_millis = params->params.timeout_millis;
|
| - if (timeout_millis <= 0) {
|
| - return RespondNow(ErrorWithArguments(
|
| - Transmit::Results::Create(STATUS_INVALIDREQUEST),
|
| - kInvalidTimeoutError));
|
| - }
|
| - if (timeout_millis > kMaxTransmitTimeout)
|
| - timeout_millis = kMaxTransmitTimeout;
|
| -
|
| - // Start transmission.
|
| - Status status = api->StartTransmit(extension_id(), params->params, token_str);
|
| - return RespondNow(ArgumentList(Transmit::Results::Create(status)));
|
| -}
|
| -
|
| -ExtensionFunction::ResponseAction AudioModemStopTransmitFunction::Run() {
|
| - std::unique_ptr<StopTransmit::Params> params(
|
| - StopTransmit::Params::Create(*args_));
|
| - EXTENSION_FUNCTION_VALIDATE(params.get());
|
| -
|
| - Status status = AudioModemAPI::GetFactoryInstance()->Get(browser_context())
|
| - ->StopTransmit(extension_id(), AudioTypeForBand(params->band));
|
| - return RespondNow(ArgumentList(StopTransmit::Results::Create(status)));
|
| -}
|
| -
|
| -ExtensionFunction::ResponseAction AudioModemReceiveFunction::Run() {
|
| - std::unique_ptr<Receive::Params> params(Receive::Params::Create(*args_));
|
| - EXTENSION_FUNCTION_VALIDATE(params.get());
|
| - AudioModemAPI* api =
|
| - AudioModemAPI::GetFactoryInstance()->Get(browser_context());
|
| - if (api->init_failed()) {
|
| - return RespondNow(ErrorWithArguments(
|
| - Transmit::Results::Create(STATUS_CODERERROR),
|
| - kInitFailedError));
|
| - }
|
| -
|
| - // Check the timeout.
|
| - int64_t timeout_millis = params->params.timeout_millis;
|
| - if (timeout_millis <= 0) {
|
| - return RespondNow(ErrorWithArguments(
|
| - Receive::Results::Create(STATUS_INVALIDREQUEST),
|
| - kInvalidTimeoutError));
|
| - }
|
| - if (timeout_millis > kMaxReceiveTimeout)
|
| - timeout_millis = kMaxReceiveTimeout;
|
| -
|
| - // Start receiving.
|
| - api->StartReceive(extension_id(), params->params);
|
| - return RespondNow(ArgumentList(Receive::Results::Create(STATUS_SUCCESS)));
|
| -}
|
| -
|
| -ExtensionFunction::ResponseAction AudioModemStopReceiveFunction::Run() {
|
| - std::unique_ptr<StopReceive::Params> params(
|
| - StopReceive::Params::Create(*args_));
|
| - EXTENSION_FUNCTION_VALIDATE(params.get());
|
| -
|
| - Status status = AudioModemAPI::GetFactoryInstance()->Get(browser_context())
|
| - ->StopReceive(extension_id(), AudioTypeForBand(params->band));
|
| - return RespondNow(ArgumentList(StopReceive::Results::Create(status)));
|
| -}
|
| -
|
| -} // namespace extensions
|
|
|