Home | History | Annotate | Download | only in media
      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 "base/command_line.h"
      6 #include "base/json/json_reader.h"
      7 #include "base/strings/string_util.h"
      8 #include "chrome/browser/media/webrtc_browsertest_base.h"
      9 #include "chrome/browser/media/webrtc_browsertest_common.h"
     10 #include "chrome/browser/ui/browser.h"
     11 #include "chrome/browser/ui/browser_tabstrip.h"
     12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     13 #include "chrome/common/chrome_switches.h"
     14 #include "chrome/test/base/in_process_browser_test.h"
     15 #include "chrome/test/base/ui_test_utils.h"
     16 #include "content/public/test/browser_test_utils.h"
     17 #include "media/audio/audio_manager.h"
     18 #include "media/base/media_switches.h"
     19 #include "net/test/embedded_test_server/embedded_test_server.h"
     20 
     21 namespace {
     22 
     23 const char kMainWebrtcTestHtmlPage[] = "/webrtc/webrtc_jsep01_test.html";
     24 
     25 const char kDeviceKindAudioInput[] = "audioinput";
     26 const char kDeviceKindVideoInput[] = "videoinput";
     27 const char kDeviceKindAudioOutput[] = "audiooutput";
     28 
     29 const char kSourceKindAudioInput[] = "audio";
     30 const char kSourceKindVideoInput[] = "video";
     31 
     32 }  // namespace
     33 
     34 // Integration test for WebRTC getMediaDevices. It always uses fake devices.
     35 // It needs to be a browser test (and not content browser test) to be able to
     36 // test that labels are cleared or not depending on if access to devices has
     37 // been granted.
     38 class WebRtcGetMediaDevicesBrowserTest
     39     : public WebRtcTestBase,
     40       public testing::WithParamInterface<bool> {
     41  public:
     42   WebRtcGetMediaDevicesBrowserTest()
     43       : has_audio_output_devices_initialized_(false),
     44         has_audio_output_devices_(false) {}
     45 
     46   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
     47     DetectErrorsInJavaScript();  // Look for errors in our rather complex js.
     48   }
     49 
     50   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     51     // Ensure the infobar is enabled, since we expect that in this test.
     52     EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
     53 
     54     // Always use fake devices.
     55     command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
     56   }
     57 
     58  protected:
     59   // This is used for media devices and sources.
     60   struct MediaDeviceInfo {
     61     std::string device_id;  // Domain specific device ID.
     62     std::string kind;
     63     std::string label;
     64     std::string group_id;
     65   };
     66 
     67   bool HasOutputDevices() {
     68     // There's no fake audio output devices supported yet. We can't test audio
     69     // output devices on bots with no output devices, so skip testing for that
     70     // on such bots. We cache the result since querying for devices can take
     71     // considerable time.
     72     if (!has_audio_output_devices_initialized_) {
     73       has_audio_output_devices_ =
     74           media::AudioManager::Get()->HasAudioOutputDevices();
     75       has_audio_output_devices_initialized_ = true;
     76     }
     77     return has_audio_output_devices_;
     78   }
     79 
     80   // If |get_sources| is true, use getSources API and leave groupId empty,
     81   // otherwise use getMediaDevices API.
     82   void GetMediaDevicesOrSources(content::WebContents* tab,
     83                                 std::vector<MediaDeviceInfo>* devices,
     84                                 bool get_sources) {
     85     std::string devices_as_json =
     86         ExecuteJavascript(get_sources ? "getSources()" : "getMediaDevices()",
     87                           tab);
     88     EXPECT_FALSE(devices_as_json.empty());
     89 
     90     int error_code;
     91     std::string error_message;
     92     scoped_ptr<base::Value> value(
     93         base::JSONReader::ReadAndReturnError(devices_as_json,
     94                                              base::JSON_ALLOW_TRAILING_COMMAS,
     95                                              &error_code,
     96                                              &error_message));
     97 
     98     ASSERT_TRUE(value.get() != NULL) << error_message;
     99     EXPECT_EQ(value->GetType(), base::Value::TYPE_LIST);
    100 
    101     base::ListValue* values;
    102     ASSERT_TRUE(value->GetAsList(&values));
    103     ASSERT_FALSE(values->empty());
    104     bool found_audio_input = false;
    105     bool found_video_input = false;
    106     bool found_audio_output = false;
    107 
    108     for (base::ListValue::iterator it = values->begin();
    109          it != values->end(); ++it) {
    110       const base::DictionaryValue* dict;
    111       MediaDeviceInfo device;
    112       ASSERT_TRUE((*it)->GetAsDictionary(&dict));
    113       ASSERT_TRUE(dict->GetString(get_sources ? "id" : "deviceId",
    114                                   &device.device_id));
    115       ASSERT_TRUE(dict->GetString("kind", &device.kind));
    116       ASSERT_TRUE(dict->GetString("label", &device.label));
    117       if (!get_sources)
    118         ASSERT_TRUE(dict->GetString("groupId", &device.group_id));
    119 
    120       // Should be HMAC SHA256.
    121       EXPECT_EQ(64ul, device.device_id.length());
    122       EXPECT_TRUE(base::ContainsOnlyChars(device.device_id,
    123                                           "0123456789abcdef"));
    124 
    125       const char* kAudioInputKind =
    126           get_sources ? kSourceKindAudioInput : kDeviceKindAudioInput;
    127       const char* kVideoInputKind =
    128           get_sources ? kSourceKindVideoInput : kDeviceKindVideoInput;
    129       if (get_sources) {
    130         EXPECT_TRUE(device.kind == kAudioInputKind ||
    131                     device.kind == kVideoInputKind);
    132       } else {
    133         EXPECT_TRUE(device.kind == kAudioInputKind ||
    134                     device.kind == kVideoInputKind ||
    135                     device.kind == kDeviceKindAudioOutput);
    136       }
    137       if (device.kind == kAudioInputKind) {
    138         found_audio_input = true;
    139       } else if (device.kind == kVideoInputKind) {
    140         found_video_input = true;
    141       } else {
    142         found_audio_output = true;
    143       }
    144 
    145       // getSources doesn't have group ID support. getMediaDevices doesn't have
    146       // group ID support for video input devices.
    147       if (get_sources || device.kind == kDeviceKindVideoInput) {
    148         EXPECT_TRUE(device.group_id.empty());
    149       } else {
    150         EXPECT_FALSE(device.group_id.empty());
    151       }
    152 
    153       devices->push_back(device);
    154     }
    155 
    156     EXPECT_TRUE(found_audio_input);
    157     EXPECT_TRUE(found_video_input);
    158     if (get_sources) {
    159       EXPECT_FALSE(found_audio_output);
    160     } else {
    161       EXPECT_EQ(HasOutputDevices(), found_audio_output);
    162     }
    163   }
    164 
    165   void GetMediaDevices(content::WebContents* tab,
    166                      std::vector<MediaDeviceInfo>* devices) {
    167     GetMediaDevicesOrSources(tab, devices, false);
    168   }
    169 
    170   void GetSources(content::WebContents* tab,
    171                   std::vector<MediaDeviceInfo>* sources) {
    172     GetMediaDevicesOrSources(tab, sources, true);
    173   }
    174 
    175   bool has_audio_output_devices_initialized_;
    176   bool has_audio_output_devices_;
    177 };
    178 
    179 static const bool kParamsToRunTestsWith[] = { false, true };
    180 INSTANTIATE_TEST_CASE_P(WebRtcGetMediaDevicesBrowserTests,
    181                         WebRtcGetMediaDevicesBrowserTest,
    182                         testing::ValuesIn(kParamsToRunTestsWith));
    183 
    184 // getMediaDevices has been removed and will be replaced
    185 // MediaDevices.enumerateDevices. http://crbug.com/388648.
    186 IN_PROC_BROWSER_TEST_P(WebRtcGetMediaDevicesBrowserTest,
    187                        DISABLED_GetMediaDevicesWithoutAccess) {
    188   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    189   GURL url(embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
    190   ui_test_utils::NavigateToURL(browser(), url);
    191   content::WebContents* tab =
    192       browser()->tab_strip_model()->GetActiveWebContents();
    193 
    194   std::vector<MediaDeviceInfo> devices;
    195   GetMediaDevices(tab, &devices);
    196 
    197   // Labels should be empty if access has not been allowed.
    198   for (std::vector<MediaDeviceInfo>::iterator it = devices.begin();
    199        it != devices.end(); ++it) {
    200     EXPECT_TRUE(it->label.empty());
    201   }
    202 }
    203 
    204 // getMediaDevices has been removed and will be replaced
    205 // MediaDevices.enumerateDevices. http://crbug.com/388648.
    206 // Disabled, fails due to http://crbug.com/382391.
    207 IN_PROC_BROWSER_TEST_P(WebRtcGetMediaDevicesBrowserTest,
    208                        DISABLED_GetMediaDevicesWithAccess) {
    209   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    210   GURL url(embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
    211   ui_test_utils::NavigateToURL(browser(), url);
    212   content::WebContents* tab =
    213       browser()->tab_strip_model()->GetActiveWebContents();
    214 
    215   GetUserMediaAndAccept(tab);
    216 
    217   std::vector<MediaDeviceInfo> devices;
    218   GetMediaDevices(tab, &devices);
    219 
    220   // Labels should be non-empty if access has been allowed.
    221   for (std::vector<MediaDeviceInfo>::iterator it = devices.begin();
    222        it != devices.end(); ++it) {
    223     EXPECT_TRUE(!it->label.empty());
    224   }
    225 }
    226 
    227 // getMediaDevices has been removed and will be replaced
    228 // MediaDevices.enumerateDevices. http://crbug.com/388648.
    229 IN_PROC_BROWSER_TEST_P(WebRtcGetMediaDevicesBrowserTest,
    230                        DISABLED_GetMediaDevicesEqualsGetSourcesWithoutAccess) {
    231   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    232   GURL url(embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
    233   ui_test_utils::NavigateToURL(browser(), url);
    234   content::WebContents* tab =
    235       browser()->tab_strip_model()->GetActiveWebContents();
    236 
    237   std::vector<MediaDeviceInfo> devices;
    238   GetMediaDevices(tab, &devices);
    239 
    240   std::vector<MediaDeviceInfo> sources;
    241   GetSources(tab, &sources);
    242 
    243   std::vector<MediaDeviceInfo>::iterator sources_it = sources.begin();
    244   for (std::vector<MediaDeviceInfo>::iterator devices_it = devices.begin();
    245        devices_it != devices.end(); ++devices_it) {
    246     if (devices_it->kind == kDeviceKindAudioOutput)
    247       continue;
    248     EXPECT_STREQ(devices_it->device_id.c_str(), sources_it->device_id.c_str());
    249     if (devices_it->kind == kDeviceKindAudioInput) {
    250       EXPECT_STREQ(kSourceKindAudioInput, sources_it->kind.c_str());
    251     } else {
    252       EXPECT_STREQ(kSourceKindVideoInput, sources_it->kind.c_str());
    253     }
    254     EXPECT_TRUE(devices_it->label.empty());
    255     EXPECT_TRUE(sources_it->label.empty());
    256     ++sources_it;
    257   }
    258   EXPECT_EQ(sources.end(), sources_it);
    259 }
    260 
    261 // getMediaDevices has been removed and will be replaced
    262 // MediaDevices.enumerateDevices. http://crbug.com/388648.
    263 // Disabled, fails due to http://crbug.com/382391.
    264 IN_PROC_BROWSER_TEST_P(WebRtcGetMediaDevicesBrowserTest,
    265                        DISABLED_GetMediaDevicesEqualsGetSourcesWithAccess) {
    266   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    267   GURL url(embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
    268   ui_test_utils::NavigateToURL(browser(), url);
    269   content::WebContents* tab =
    270       browser()->tab_strip_model()->GetActiveWebContents();
    271 
    272   GetUserMediaAndAccept(tab);
    273 
    274   std::vector<MediaDeviceInfo> devices;
    275   GetMediaDevices(tab, &devices);
    276 
    277   std::vector<MediaDeviceInfo> sources;
    278   GetSources(tab, &sources);
    279 
    280   std::vector<MediaDeviceInfo>::iterator sources_it = sources.begin();
    281   for (std::vector<MediaDeviceInfo>::iterator devices_it = devices.begin();
    282        devices_it != devices.end(); ++devices_it) {
    283     if (devices_it->kind == kDeviceKindAudioOutput)
    284       continue;
    285     EXPECT_STREQ(devices_it->device_id.c_str(), sources_it->device_id.c_str());
    286     if (devices_it->kind == kDeviceKindAudioInput) {
    287       EXPECT_STREQ(kSourceKindAudioInput, sources_it->kind.c_str());
    288     } else {
    289       EXPECT_STREQ(kSourceKindVideoInput, sources_it->kind.c_str());
    290     }
    291     EXPECT_TRUE(!devices_it->label.empty());
    292     EXPECT_STREQ(devices_it->label.c_str(), sources_it->label.c_str());
    293     ++sources_it;
    294   }
    295   EXPECT_EQ(sources.end(), sources_it);
    296 }
    297