11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/json/json_writer.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/string_util.h"
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/strings/stringprintf.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/threading/platform_thread.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/time/time.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/browser_process.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/component_loader.h"
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_apitest.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_function_test_utils.h"
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/extension_tab_util.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/media/webrtc_log_uploader.h"
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/media_device_id.h"
251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/web_contents.h"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/test/browser_test_utils.h"
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/permissions/permission_set.h"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "media/audio/audio_manager.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/audio/audio_manager_base.h"
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h"
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using base::JSONWriter;
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using content::RenderViewHost;
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using content::WebContents;
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using media::AudioDeviceNames;
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using media::AudioManager;
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace extensions {
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extension_function_test_utils::RunFunctionAndReturnError;
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using extension_function_test_utils::RunFunctionAndReturnSingleResult;
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class AudioWaitingExtensionTest : public ExtensionApiTest {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void WaitUntilAudioIsPlaying(WebContents* tab) {
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Wait for audio to start playing. We gate this on there being one
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // or more AudioOutputController objects for our tab.
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool audio_playing = false;
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) {
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      tab->GetRenderViewHost()->GetAudioOutputControllers(
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          base::Bind(OnAudioControllers, &audio_playing));
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::MessageLoop::current()->RunUntilIdle();
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (audio_playing)
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!audio_playing)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FAIL() << "Audio did not start playing within ~5 seconds.";
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Used by the test above to wait until audio is playing.
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static void OnAudioControllers(
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bool* audio_playing,
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const RenderViewHost::AudioOutputControllerList& list) {
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!list.empty())
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      *audio_playing = true;
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class WebrtcAudioPrivateTest : public AudioWaitingExtensionTest {
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public:
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebrtcAudioPrivateTest()
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      : enumeration_event_(false, false) {
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void SetUpOnMainThread() OVERRIDE {
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    AudioWaitingExtensionTest::SetUpOnMainThread();
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Needs to happen after chrome's schemes are added.
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    source_url_ = GURL("chrome-extension://fakeid012345678/fakepage.html");
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) protected:
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string InvokeGetActiveSink(int tab_id) {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue parameters;
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    parameters.AppendInteger(tab_id);
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string parameter_string;
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    JSONWriter::Write(&parameters, &parameter_string);
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_refptr<WebrtcAudioPrivateGetActiveSinkFunction> function =
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        new WebrtcAudioPrivateGetActiveSinkFunction();
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function->set_source_url(source_url_);
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<base::Value> result(
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        RunFunctionAndReturnSingleResult(function.get(),
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                         parameter_string,
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                         browser()));
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string device_id;
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    result->GetAsString(&device_id);
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return device_id;
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> InvokeGetSinks(base::ListValue** sink_list) {
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<WebrtcAudioPrivateGetSinksFunction> function =
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new WebrtcAudioPrivateGetSinksFunction();
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function->set_source_url(source_url_);
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::Value> result(
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        RunFunctionAndReturnSingleResult(function.get(), "[]", browser()));
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result->GetAsList(sink_list);
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return result.Pass();
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Synchronously (from the calling thread's point of view) runs the
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // given enumeration function on the device thread. On return,
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // |device_names| has been filled with the device names resulting
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // from that call.
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void GetAudioDeviceNames(
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      void (AudioManager::*EnumerationFunc)(AudioDeviceNames*),
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      AudioDeviceNames* device_names) {
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    AudioManager* audio_manager = AudioManager::Get();
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!audio_manager->GetWorkerTaskRunner()->BelongsToCurrentThread()) {
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      audio_manager->GetWorkerTaskRunner()->PostTask(
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          FROM_HERE,
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          base::Bind(&WebrtcAudioPrivateTest::GetAudioDeviceNames, this,
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     EnumerationFunc, device_names));
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      enumeration_event_.Wait();
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      (audio_manager->*EnumerationFunc)(device_names);
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      enumeration_event_.Signal();
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Synchronously (from the calling thread's point of view) retrieve the
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // device id in the |origin| on the IO thread. On return,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |id_in_origin| contains the id |raw_device_id| is known by in
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the origin.
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void GetIDInOrigin(content::ResourceContext* resource_context,
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     GURL origin,
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const std::string& raw_device_id,
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     std::string* id_in_origin) {
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      content::BrowserThread::PostTask(
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          content::BrowserThread::IO, FROM_HERE,
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::Bind(&WebrtcAudioPrivateTest::GetIDInOrigin,
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     this, resource_context, origin, raw_device_id,
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     id_in_origin));
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      enumeration_event_.Wait();
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else {
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *id_in_origin = content::GetHMACForMediaDeviceID(
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          resource_context->GetMediaDeviceIDSalt(),
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          origin,
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          raw_device_id);
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      enumeration_event_.Signal();
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Event used to signal completion of enumeration.
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::WaitableEvent enumeration_event_;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL source_url_;
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)};
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(OS_MACOSX)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// http://crbug.com/334579
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetSinks) {
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AudioDeviceNames devices;
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GetAudioDeviceNames(&AudioManager::GetAudioOutputDeviceNames, &devices);
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::ListValue* sink_list = NULL;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> result = InvokeGetSinks(&sink_list);
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string result_string;
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  JSONWriter::Write(result.get(), &result_string);
1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  VLOG(2) << result_string;
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(devices.size(), sink_list->GetSize());
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Iterate through both lists in lockstep and compare. The order
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // should be identical.
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  size_t ix = 0;
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AudioDeviceNames::const_iterator it = devices.begin();
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (; ix < sink_list->GetSize() && it != devices.end();
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       ++ix, ++it) {
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::DictionaryValue* dict = NULL;
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    sink_list->GetDictionary(ix, &dict);
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string sink_id;
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    dict->GetString("sinkId", &sink_id);
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string expected_id;
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (it->unique_id.empty() ||
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        it->unique_id == media::AudioManagerBase::kDefaultDeviceId) {
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      expected_id = media::AudioManagerBase::kDefaultDeviceId;
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetIDInOrigin(profile()->GetResourceContext(),
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    source_url_.GetOrigin(),
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    it->unique_id,
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    &expected_id);
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(expected_id, sink_id);
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string sink_label;
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    dict->GetString("sinkLabel", &sink_label);
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_EQ(it->device_name, sink_label);
2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // TODO(joi): Verify the contents of these once we start actually
2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // filling them in.
2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_TRUE(dict->HasKey("isDefault"));
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_TRUE(dict->HasKey("isReady"));
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_TRUE(dict->HasKey("sampleRate"));
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // OS_MACOSX
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// This exercises the case where you have a tab with no active media
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// stream and try to retrieve the currently active audio sink.
2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetActiveSinkNoMediaStream) {
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int tab_id = ExtensionTabUtil::GetTabId(tab);
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::ListValue parameters;
2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  parameters.AppendInteger(tab_id);
2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string parameter_string;
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  JSONWriter::Write(&parameters, &parameter_string);
2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<WebrtcAudioPrivateGetActiveSinkFunction> function =
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new WebrtcAudioPrivateGetActiveSinkFunction();
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  function->set_source_url(source_url_);
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<base::Value> result(
2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      RunFunctionAndReturnSingleResult(function.get(),
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       parameter_string,
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                       browser()));
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string result_string;
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  JSONWriter::Write(result.get(), &result_string);
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ("\"\"", result_string);
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// This exercises the case where you have a tab with no active media
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// stream and try to set the audio sink.
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, SetActiveSinkNoMediaStream) {
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int tab_id = ExtensionTabUtil::GetTabId(tab);
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue parameters;
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  parameters.AppendInteger(tab_id);
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  parameters.AppendString("no such id");
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string parameter_string;
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  JSONWriter::Write(&parameters, &parameter_string);
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function =
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new WebrtcAudioPrivateSetActiveSinkFunction();
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  function->set_source_url(source_url_);
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string error(RunFunctionAndReturnError(function.get(),
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                              parameter_string,
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                              browser()));
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ(base::StringPrintf("No active stream for tab with id: %d.", tab_id),
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            error);
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) {
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // First retrieve the list of all sinks, so that we can run a test
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // where we set the active sink to each of the different available
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // sinks in turn.
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* sink_list = NULL;
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> result = InvokeGetSinks(&sink_list);
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ASSERT_TRUE(StartEmbeddedTestServer());
2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Open a normal page that uses an audio sink.
2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ui_test_utils::NavigateToURL(
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      browser(),
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GURL(embedded_test_server()->GetURL("/extensions/loop_audio.html")));
2751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int tab_id = ExtensionTabUtil::GetTabId(tab);
2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WaitUntilAudioIsPlaying(tab);
2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string current_device = InvokeGetActiveSink(tab_id);
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  VLOG(2) << "Before setting, current device: " << current_device;
2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_NE("", current_device);
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Set to each of the other devices in turn.
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t ix = 0; ix < sink_list->GetSize(); ++ix) {
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* dict = NULL;
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sink_list->GetDictionary(ix, &dict);
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string target_device;
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict->GetString("sinkId", &target_device);
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue parameters;
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    parameters.AppendInteger(tab_id);
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    parameters.AppendString(target_device);
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string parameter_string;
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    JSONWriter::Write(&parameters, &parameter_string);
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_refptr<WebrtcAudioPrivateSetActiveSinkFunction> function =
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new WebrtcAudioPrivateSetActiveSinkFunction();
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function->set_source_url(source_url_);
3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        function.get(), parameter_string, browser()));
3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The function was successful if the above invocation doesn't
3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // fail. Just for kicks, also check that it returns no result.
3051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_EQ(NULL, result.get());
3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    current_device = InvokeGetActiveSink(tab_id);
3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    VLOG(2) << "After setting to " << target_device
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            << ", current device is " << current_device;
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_EQ(target_device, current_device);
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAssociatedSink) {
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Get the list of input devices. We can cheat in the unit test and
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // run this on the main thread since nobody else will be running at
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // the same time.
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AudioDeviceNames devices;
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GetAudioDeviceNames(&AudioManager::GetAudioInputDeviceNames, &devices);
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Try to get an associated sink for each source.
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (AudioDeviceNames::const_iterator device = devices.begin();
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       device != devices.end();
3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       ++device) {
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_refptr<WebrtcAudioPrivateGetAssociatedSinkFunction> function =
326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        new WebrtcAudioPrivateGetAssociatedSinkFunction();
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function->set_source_url(source_url_);
328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string raw_device_id = device->unique_id;
330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VLOG(2) << "Trying to find associated sink for device " << raw_device_id;
331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string source_id_in_origin;
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    GURL origin(GURL("http://www.google.com/").GetOrigin());
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    GetIDInOrigin(profile()->GetResourceContext(),
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  origin,
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  raw_device_id,
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  &source_id_in_origin);
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue parameters;
3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    parameters.AppendString(origin.spec());
3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    parameters.AppendString(source_id_in_origin);
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string parameter_string;
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    JSONWriter::Write(&parameters, &parameter_string);
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<base::Value> result(
3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        RunFunctionAndReturnSingleResult(function.get(),
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                         parameter_string,
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                         browser()));
3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::string result_string;
3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    JSONWriter::Write(result.get(), &result_string);
3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    VLOG(2) << "Results: " << result_string;
3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, TriggerEvent) {
3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  WebrtcAudioPrivateEventService* service =
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      WebrtcAudioPrivateEventService::GetFactoryInstance()->Get(profile());
3571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Just trigger, without any extension listening.
3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  service->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
3601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Now load our test extension and do it again.
3621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const extensions::Extension* extension = LoadExtension(
3631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      test_data_dir_.AppendASCII("webrtc_audio_private_event_listener"));
3641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  service->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
3651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Check that the extension got the notification.
3671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::string result = ExecuteScriptInBackgroundPage(extension->id(),
3681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                     "reportIfGot()");
3691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_EQ("true", result);
3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class HangoutServicesBrowserTest : public AudioWaitingExtensionTest {
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Make sure the Hangout Services component extension gets loaded.
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ComponentLoader::EnableBackgroundExtensionsForTesting();
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    AudioWaitingExtensionTest::SetUp();
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(HangoutServicesBrowserTest,
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       RunComponentExtensionTest) {
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This runs the end-to-end JavaScript test for the Hangout Services
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // component extension, which uses the webrtcAudioPrivate API among
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // others.
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(StartEmbeddedTestServer());
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GURL url(embedded_test_server()->GetURL(
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               "/extensions/hangout_services_test.html"));
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The "externally connectable" extension permission doesn't seem to
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // like when we use 127.0.0.1 as the host, but using localhost works.
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string url_spec = url.spec();
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ReplaceFirstSubstringAfterOffset(&url_spec, 0, "127.0.0.1", "localhost");
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GURL localhost_url(url_spec);
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), localhost_url);
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WaitUntilAudioIsPlaying(tab);
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Override, i.e. disable, uploading. We don't want to try sending data to
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // servers when running the test. We don't bother about the contents of the
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // buffer |dummy|, that's tested in other tests.
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string dummy;
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_browser_process->webrtc_log_uploader()->
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      OverrideUploadWithBufferForTesting(&dummy);
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(content::ExecuteScript(tab, "browsertestRunAllTests();"));
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::TitleWatcher title_watcher(tab, base::ASCIIToUTF16("success"));
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("failure"));
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 result = title_watcher.WaitAndGetTitle();
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::ASCIIToUTF16("success"), result);
413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  g_browser_process->webrtc_log_uploader()->OverrideUploadWithBufferForTesting(
415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      NULL);
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace extensions
420