Home | History | Annotate | Download | only in copresence
      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 <cstdlib>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "base/macros.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/run_loop.h"
     14 #include "base/stl_util.h"
     15 #include "chrome/browser/extensions/api/copresence/copresence_api.h"
     16 #include "chrome/browser/extensions/extension_browsertest.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/browser/ui/browser.h"
     19 #include "chrome/test/base/in_process_browser_test.h"
     20 #include "media/base/audio_bus.h"
     21 
     22 namespace {
     23 
     24 const char kSixZeros[] = "MDAwMDAw";
     25 
     26 copresence::WhispernetClient* GetWhispernetClient(
     27     content::BrowserContext* context) {
     28   extensions::CopresenceService* service =
     29       extensions::CopresenceService::GetFactoryInstance()->Get(context);
     30   return service ? service->whispernet_client() : NULL;
     31 }
     32 
     33 // Copied from src/components/copresence/mediums/audio/audio_recorder.cc
     34 std::string AudioBusToString(scoped_refptr<media::AudioBusRefCounted> source) {
     35   std::string buffer;
     36   buffer.resize(source->frames() * source->channels() * sizeof(float));
     37   float* buffer_view = reinterpret_cast<float*>(string_as_array(&buffer));
     38 
     39   const int channels = source->channels();
     40   for (int ch = 0; ch < channels; ++ch) {
     41     for (int si = 0, di = ch; si < source->frames(); ++si, di += channels)
     42       buffer_view[di] = source->channel(ch)[si];
     43   }
     44 
     45   return buffer;
     46 }
     47 
     48 }  // namespace
     49 
     50 class ChromeWhispernetClientTest : public ExtensionBrowserTest {
     51  public:
     52   ChromeWhispernetClientTest() : context_(NULL), initialized_(false) {}
     53 
     54   virtual ~ChromeWhispernetClientTest() {}
     55 
     56   void InitializeWhispernet() {
     57     context_ = browser()->profile();
     58     run_loop_.reset(new base::RunLoop());
     59     GetWhispernetClient(context_)->Initialize(base::Bind(
     60         &ChromeWhispernetClientTest::InitCallback, base::Unretained(this)));
     61     run_loop_->Run();
     62 
     63     EXPECT_TRUE(initialized_);
     64   }
     65 
     66   void EncodeTokenAndSaveSamples(bool audible) {
     67     copresence::WhispernetClient* client = GetWhispernetClient(context_);
     68     ASSERT_TRUE(client);
     69 
     70     run_loop_.reset(new base::RunLoop());
     71     client->RegisterSamplesCallback(base::Bind(
     72         &ChromeWhispernetClientTest::SamplesCallback, base::Unretained(this)));
     73     expected_token_ = kSixZeros;
     74     expected_audible_ = audible;
     75 
     76     client->EncodeToken(kSixZeros, audible);
     77     run_loop_->Run();
     78 
     79     EXPECT_GT(saved_samples_->frames(), 0);
     80   }
     81 
     82   void DecodeSamplesAndVerifyToken(bool expect_audible) {
     83     copresence::WhispernetClient* client = GetWhispernetClient(context_);
     84     ASSERT_TRUE(client);
     85 
     86     run_loop_.reset(new base::RunLoop());
     87     client->RegisterTokensCallback(base::Bind(
     88         &ChromeWhispernetClientTest::TokensCallback, base::Unretained(this)));
     89     expected_token_ = kSixZeros;
     90     expected_audible_ = expect_audible;
     91 
     92     ASSERT_GT(saved_samples_->frames(), 0);
     93 
     94     // Convert our single channel samples to two channel. Decode samples
     95     // expects 2 channel data.
     96     scoped_refptr<media::AudioBusRefCounted> samples_bus =
     97         media::AudioBusRefCounted::Create(2, saved_samples_->frames());
     98     memcpy(samples_bus->channel(0),
     99            saved_samples_->channel(0),
    100            sizeof(float) * saved_samples_->frames());
    101     memcpy(samples_bus->channel(1),
    102            saved_samples_->channel(0),
    103            sizeof(float) * saved_samples_->frames());
    104 
    105     client->DecodeSamples(AudioBusToString(samples_bus));
    106     run_loop_->Run();
    107   }
    108 
    109   void DetectBroadcast() {
    110     copresence::WhispernetClient* client = GetWhispernetClient(context_);
    111     ASSERT_TRUE(client);
    112 
    113     run_loop_.reset(new base::RunLoop());
    114     client->RegisterDetectBroadcastCallback(
    115         base::Bind(&ChromeWhispernetClientTest::DetectBroadcastCallback,
    116                    base::Unretained(this)));
    117     client->DetectBroadcast();
    118     run_loop_->Run();
    119   }
    120 
    121  protected:
    122   void InitCallback(bool success) {
    123     EXPECT_TRUE(success);
    124     initialized_ = true;
    125     ASSERT_TRUE(run_loop_);
    126     run_loop_->Quit();
    127   }
    128 
    129   void SamplesCallback(
    130       const std::string& token,
    131       bool audible,
    132       const scoped_refptr<media::AudioBusRefCounted>& samples) {
    133     EXPECT_EQ(expected_token_, token);
    134     EXPECT_EQ(expected_audible_, audible);
    135     saved_samples_ = samples;
    136     ASSERT_TRUE(run_loop_);
    137     run_loop_->Quit();
    138   }
    139 
    140   void TokensCallback(const std::vector<copresence::AudioToken>& tokens) {
    141     ASSERT_TRUE(run_loop_);
    142     run_loop_->Quit();
    143 
    144     EXPECT_EQ(expected_token_, tokens[0].token);
    145     EXPECT_EQ(expected_audible_, tokens[0].audible);
    146   }
    147 
    148   void DetectBroadcastCallback(bool success) {
    149     EXPECT_TRUE(success);
    150     ASSERT_TRUE(run_loop_);
    151     run_loop_->Quit();
    152   }
    153 
    154  private:
    155   scoped_ptr<base::RunLoop> run_loop_;
    156   content::BrowserContext* context_;
    157 
    158   std::string expected_token_;
    159   bool expected_audible_;
    160   scoped_refptr<media::AudioBusRefCounted> saved_samples_;
    161 
    162   bool initialized_;
    163 
    164   DISALLOW_COPY_AND_ASSIGN(ChromeWhispernetClientTest);
    165 };
    166 
    167 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, Initialize) {
    168   InitializeWhispernet();
    169 }
    170 
    171 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, EncodeToken) {
    172   InitializeWhispernet();
    173   EncodeTokenAndSaveSamples(false);
    174 }
    175 
    176 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, DecodeSamples) {
    177   InitializeWhispernet();
    178   EncodeTokenAndSaveSamples(false);
    179   DecodeSamplesAndVerifyToken(false);
    180 }
    181 
    182 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, DetectBroadcast) {
    183   InitializeWhispernet();
    184   EncodeTokenAndSaveSamples(false);
    185   DecodeSamplesAndVerifyToken(false);
    186   DetectBroadcast();
    187 }
    188 
    189 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, Audible) {
    190   InitializeWhispernet();
    191   EncodeTokenAndSaveSamples(true);
    192   DecodeSamplesAndVerifyToken(true);
    193 }
    194