blob: 43e75dd2a0f46f390d31fa205baab65d387a9a64 [file] [log] [blame]
// Copyright 2014 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/copresence/chrome_whispernet_client.h"
#include <cstdlib>
#include <string>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "chrome/browser/extensions/api/copresence/copresence_api.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "media/base/audio_bus.h"
namespace {
const char kSixZeros[] = "MDAwMDAw";
copresence::WhispernetClient* GetWhispernetClient(
content::BrowserContext* context) {
extensions::CopresenceService* service =
extensions::CopresenceService::GetFactoryInstance()->Get(context);
return service ? service->whispernet_client() : NULL;
}
// Copied from src/components/copresence/mediums/audio/audio_recorder.cc
std::string AudioBusToString(scoped_refptr<media::AudioBusRefCounted> source) {
std::string buffer;
buffer.resize(source->frames() * source->channels() * sizeof(float));
float* buffer_view = reinterpret_cast<float*>(string_as_array(&buffer));
const int channels = source->channels();
for (int ch = 0; ch < channels; ++ch) {
for (int si = 0, di = ch; si < source->frames(); ++si, di += channels)
buffer_view[di] = source->channel(ch)[si];
}
return buffer;
}
} // namespace
class ChromeWhispernetClientTest : public ExtensionBrowserTest {
public:
ChromeWhispernetClientTest() : context_(NULL), initialized_(false) {}
virtual ~ChromeWhispernetClientTest() {}
void InitializeWhispernet() {
context_ = browser()->profile();
run_loop_.reset(new base::RunLoop());
GetWhispernetClient(context_)->Initialize(base::Bind(
&ChromeWhispernetClientTest::InitCallback, base::Unretained(this)));
run_loop_->Run();
EXPECT_TRUE(initialized_);
}
void EncodeTokenAndSaveSamples(bool audible) {
copresence::WhispernetClient* client = GetWhispernetClient(context_);
ASSERT_TRUE(client);
run_loop_.reset(new base::RunLoop());
client->RegisterSamplesCallback(base::Bind(
&ChromeWhispernetClientTest::SamplesCallback, base::Unretained(this)));
expected_token_ = kSixZeros;
expected_audible_ = audible;
client->EncodeToken(kSixZeros, audible);
run_loop_->Run();
EXPECT_GT(saved_samples_->frames(), 0);
}
void DecodeSamplesAndVerifyToken(bool expect_audible) {
copresence::WhispernetClient* client = GetWhispernetClient(context_);
ASSERT_TRUE(client);
run_loop_.reset(new base::RunLoop());
client->RegisterTokensCallback(base::Bind(
&ChromeWhispernetClientTest::TokensCallback, base::Unretained(this)));
expected_token_ = kSixZeros;
expected_audible_ = expect_audible;
ASSERT_GT(saved_samples_->frames(), 0);
// Convert our single channel samples to two channel. Decode samples
// expects 2 channel data.
scoped_refptr<media::AudioBusRefCounted> samples_bus =
media::AudioBusRefCounted::Create(2, saved_samples_->frames());
memcpy(samples_bus->channel(0),
saved_samples_->channel(0),
sizeof(float) * saved_samples_->frames());
memcpy(samples_bus->channel(1),
saved_samples_->channel(0),
sizeof(float) * saved_samples_->frames());
client->DecodeSamples(AudioBusToString(samples_bus));
run_loop_->Run();
}
void DetectBroadcast() {
copresence::WhispernetClient* client = GetWhispernetClient(context_);
ASSERT_TRUE(client);
run_loop_.reset(new base::RunLoop());
client->RegisterDetectBroadcastCallback(
base::Bind(&ChromeWhispernetClientTest::DetectBroadcastCallback,
base::Unretained(this)));
client->DetectBroadcast();
run_loop_->Run();
}
protected:
void InitCallback(bool success) {
EXPECT_TRUE(success);
initialized_ = true;
ASSERT_TRUE(run_loop_);
run_loop_->Quit();
}
void SamplesCallback(
const std::string& token,
bool audible,
const scoped_refptr<media::AudioBusRefCounted>& samples) {
EXPECT_EQ(expected_token_, token);
EXPECT_EQ(expected_audible_, audible);
saved_samples_ = samples;
ASSERT_TRUE(run_loop_);
run_loop_->Quit();
}
void TokensCallback(const std::vector<copresence::AudioToken>& tokens) {
ASSERT_TRUE(run_loop_);
run_loop_->Quit();
EXPECT_EQ(expected_token_, tokens[0].token);
EXPECT_EQ(expected_audible_, tokens[0].audible);
}
void DetectBroadcastCallback(bool success) {
EXPECT_TRUE(success);
ASSERT_TRUE(run_loop_);
run_loop_->Quit();
}
private:
scoped_ptr<base::RunLoop> run_loop_;
content::BrowserContext* context_;
std::string expected_token_;
bool expected_audible_;
scoped_refptr<media::AudioBusRefCounted> saved_samples_;
bool initialized_;
DISALLOW_COPY_AND_ASSIGN(ChromeWhispernetClientTest);
};
IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, Initialize) {
InitializeWhispernet();
}
IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, EncodeToken) {
InitializeWhispernet();
EncodeTokenAndSaveSamples(false);
}
IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, DecodeSamples) {
InitializeWhispernet();
EncodeTokenAndSaveSamples(false);
DecodeSamplesAndVerifyToken(false);
}
IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, DetectBroadcast) {
InitializeWhispernet();
EncodeTokenAndSaveSamples(false);
DecodeSamplesAndVerifyToken(false);
DetectBroadcast();
}
IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, Audible) {
InitializeWhispernet();
EncodeTokenAndSaveSamples(true);
DecodeSamplesAndVerifyToken(true);
}