No dual_mode on Win10+ shortcuts.
[chromium-blink-merge.git] / chrome / browser / media / chrome_webrtc_apprtc_browsertest.cc
blob102801c6164d844ea79b8c8d1d39a5df0eeab633
1 // Copyright 2013 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.
5 #include "base/command_line.h"
6 #include "base/files/file_enumerator.h"
7 #include "base/path_service.h"
8 #include "base/process/launch.h"
9 #include "base/rand_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/infobars/infobar_responder.h"
13 #include "chrome/browser/infobars/infobar_service.h"
14 #include "chrome/browser/media/webrtc_browsertest_base.h"
15 #include "chrome/browser/media/webrtc_browsertest_common.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_tabstrip.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "media/base/media_switches.h"
24 #include "net/test/python_utils.h"
25 #include "ui/gl/gl_switches.h"
27 // You need this solution to run this test. The solution will download appengine
28 // and the apprtc code for you.
29 const char kAdviseOnGclientSolution[] =
30 "You need to add this solution to your .gclient to run this test:\n"
31 "{\n"
32 " \"name\" : \"webrtc.DEPS\",\n"
33 " \"url\" : \"https://chromium.googlesource.com/chromium/deps/"
34 "webrtc/webrtc.DEPS\",\n"
35 "}";
36 const char kTitlePageOfAppEngineAdminPage[] = "Instances";
38 const char kIsApprtcCallUpJavascript[] =
39 "var remoteVideo = document.querySelector('#remote-video');"
40 "var remoteVideoActive ="
41 " remoteVideo != null &&"
42 " remoteVideo.classList.contains('active');"
43 "window.domAutomationController.send(remoteVideoActive.toString());";
46 // WebRTC-AppRTC integration test. Requires a real webcam and microphone
47 // on the running system. This test is not meant to run in the main browser
48 // test suite since normal tester machines do not have webcams. Chrome will use
49 // its fake camera for both tests, but Firefox will use the real webcam in the
50 // Firefox interop test. Thus, this test must on a machine with a real webcam.
52 // This test will bring up a AppRTC instance on localhost and verify that the
53 // call gets up when connecting to the same room from two tabs in a browser.
54 class WebRtcApprtcBrowserTest : public WebRtcTestBase {
55 public:
56 WebRtcApprtcBrowserTest() {}
58 void SetUpCommandLine(base::CommandLine* command_line) override {
59 EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
61 // The video playback will not work without a GPU, so force its use here.
62 command_line->AppendSwitch(switches::kUseGpuInTests);
63 base::CommandLine::ForCurrentProcess()->AppendSwitch(
64 switches::kUseFakeDeviceForMediaStream);
67 void TearDown() override {
68 // Kill any processes we may have brought up. Note: this isn't perfect,
69 // especially if the test hangs or if we're on Windows.
70 LOG(INFO) << "Entering TearDown";
71 if (dev_appserver_.IsValid())
72 dev_appserver_.Terminate(0, false);
73 if (collider_server_.IsValid())
74 collider_server_.Terminate(0, false);
75 if (firefox_.IsValid())
76 firefox_.Terminate(0, false);
77 LOG(INFO) << "Exiting TearDown";
80 protected:
81 bool LaunchApprtcInstanceOnLocalhost(const std::string& port) {
82 base::FilePath appengine_dev_appserver =
83 GetSourceDir().Append(
84 FILE_PATH_LITERAL("../google_appengine/dev_appserver.py"));
85 if (!base::PathExists(appengine_dev_appserver)) {
86 LOG(ERROR) << "Missing appengine sdk at " <<
87 appengine_dev_appserver.value() << ". " << kAdviseOnGclientSolution;
88 return false;
91 base::FilePath apprtc_dir =
92 GetSourceDir().Append(FILE_PATH_LITERAL("out/apprtc/out/app_engine"));
93 if (!base::PathExists(apprtc_dir)) {
94 LOG(ERROR) << "Missing AppRTC AppEngine app at " <<
95 apprtc_dir.value() << ". " << kAdviseOnGclientSolution;
96 return false;
98 if (!base::PathExists(apprtc_dir.Append(FILE_PATH_LITERAL("app.yaml")))) {
99 LOG(ERROR) << "The AppRTC AppEngine app at " <<
100 apprtc_dir.value() << " appears to have not been built." <<
101 "This should have been done by webrtc.DEPS scripts which invoke " <<
102 "'grunt build' on AppRTC.";
103 return false;
106 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
107 EXPECT_TRUE(GetPythonCommand(&command_line));
109 command_line.AppendArgPath(appengine_dev_appserver);
110 command_line.AppendArgPath(apprtc_dir);
111 command_line.AppendArg("--port=" + port);
112 command_line.AppendArg("--admin_port=9998");
113 command_line.AppendArg("--skip_sdk_update_check");
114 command_line.AppendArg("--clear_datastore=yes");
116 DVLOG(1) << "Running " << command_line.GetCommandLineString();
117 dev_appserver_ = base::LaunchProcess(command_line, base::LaunchOptions());
118 return dev_appserver_.IsValid();
121 bool LaunchColliderOnLocalHost(const std::string& apprtc_url,
122 const std::string& collider_port) {
123 // The go workspace should be created, and collidermain built, at the
124 // runhooks stage when webrtc.DEPS/build_apprtc_collider.py runs.
125 #if defined(OS_WIN)
126 base::FilePath collider_server = GetSourceDir().Append(
127 FILE_PATH_LITERAL("out/go-workspace/bin/collidermain.exe"));
128 #else
129 base::FilePath collider_server = GetSourceDir().Append(
130 FILE_PATH_LITERAL("out/go-workspace/bin/collidermain"));
131 #endif
132 if (!base::PathExists(collider_server)) {
133 LOG(ERROR) << "Missing Collider server binary at " <<
134 collider_server.value() << ". " << kAdviseOnGclientSolution;
135 return false;
138 base::CommandLine command_line(collider_server);
140 command_line.AppendArg("-tls=false");
141 command_line.AppendArg("-port=" + collider_port);
142 command_line.AppendArg("-room-server=" + apprtc_url);
144 DVLOG(1) << "Running " << command_line.GetCommandLineString();
145 collider_server_ = base::LaunchProcess(command_line, base::LaunchOptions());
146 return collider_server_.IsValid();
149 bool LocalApprtcInstanceIsUp() {
150 // Load the admin page and see if we manage to load it right.
151 ui_test_utils::NavigateToURL(browser(), GURL("localhost:9998"));
152 content::WebContents* tab_contents =
153 browser()->tab_strip_model()->GetActiveWebContents();
154 std::string javascript =
155 "window.domAutomationController.send(document.title)";
156 std::string result;
157 if (!content::ExecuteScriptAndExtractString(tab_contents, javascript,
158 &result))
159 return false;
161 return result == kTitlePageOfAppEngineAdminPage;
164 bool WaitForCallToComeUp(content::WebContents* tab_contents) {
165 return test::PollingWaitUntil(kIsApprtcCallUpJavascript, "true",
166 tab_contents);
169 bool EvalInJavascriptFile(content::WebContents* tab_contents,
170 const base::FilePath& path) {
171 std::string javascript;
172 if (!ReadFileToString(path, &javascript)) {
173 LOG(ERROR) << "Missing javascript code at " << path.value() << ".";
174 return false;
177 if (!content::ExecuteScript(tab_contents, javascript)) {
178 LOG(ERROR) << "Failed to execute the following javascript: " <<
179 javascript;
180 return false;
182 return true;
185 bool DetectRemoteVideoPlaying(content::WebContents* tab_contents) {
186 if (!EvalInJavascriptFile(tab_contents, GetSourceDir().Append(
187 FILE_PATH_LITERAL("chrome/test/data/webrtc/test_functions.js"))))
188 return false;
189 if (!EvalInJavascriptFile(tab_contents, GetSourceDir().Append(
190 FILE_PATH_LITERAL("chrome/test/data/webrtc/video_detector.js"))))
191 return false;
193 // The remote video tag is called remoteVideo in the AppRTC code.
194 StartDetectingVideo(tab_contents, "remote-video");
195 WaitForVideoToPlay(tab_contents);
196 return true;
199 base::FilePath GetSourceDir() {
200 base::FilePath source_dir;
201 PathService::Get(base::DIR_SOURCE_ROOT, &source_dir);
202 return source_dir;
205 bool LaunchFirefoxWithUrl(const GURL& url) {
206 base::FilePath firefox_binary =
207 GetSourceDir().Append(
208 FILE_PATH_LITERAL("../firefox-nightly/firefox/firefox"));
209 if (!base::PathExists(firefox_binary)) {
210 LOG(ERROR) << "Missing firefox binary at " <<
211 firefox_binary.value() << ". " << kAdviseOnGclientSolution;
212 return false;
214 base::FilePath firefox_launcher =
215 GetSourceDir().Append(
216 FILE_PATH_LITERAL("../webrtc.DEPS/run_firefox_webrtc.py"));
217 if (!base::PathExists(firefox_launcher)) {
218 LOG(ERROR) << "Missing firefox launcher at " <<
219 firefox_launcher.value() << ". " << kAdviseOnGclientSolution;
220 return false;
223 base::CommandLine command_line(firefox_launcher);
224 command_line.AppendSwitchPath("--binary", firefox_binary);
225 command_line.AppendSwitchASCII("--webpage", url.spec());
227 DVLOG(1) << "Running " << command_line.GetCommandLineString();
228 firefox_ = base::LaunchProcess(command_line, base::LaunchOptions());
229 return firefox_.IsValid();
232 private:
233 base::Process dev_appserver_;
234 base::Process firefox_;
235 base::Process collider_server_;
238 IN_PROC_BROWSER_TEST_F(WebRtcApprtcBrowserTest, MANUAL_WorksOnApprtc) {
239 // Disabled on Win XP: http://code.google.com/p/webrtc/issues/detail?id=2703.
240 if (OnWinXp())
241 return;
243 DetectErrorsInJavaScript();
244 ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost("9999"));
245 ASSERT_TRUE(LaunchColliderOnLocalHost("http://localhost:9999", "8089"));
246 while (!LocalApprtcInstanceIsUp())
247 DVLOG(1) << "Waiting for AppRTC to come up...";
249 GURL room_url = GURL("http://localhost:9999/r/some_room"
250 "?wshpp=localhost:8089&wstls=false");
252 // Set up the left tab.
253 chrome::AddTabAt(browser(), GURL(), -1, true);
254 content::WebContents* left_tab =
255 browser()->tab_strip_model()->GetActiveWebContents();
256 PermissionBubbleManager::FromWebContents(left_tab)
257 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
258 InfoBarResponder left_infobar_responder(
259 InfoBarService::FromWebContents(left_tab), InfoBarResponder::ACCEPT);
260 ui_test_utils::NavigateToURL(browser(), room_url);
262 // Set up the right tab.
263 chrome::AddTabAt(browser(), GURL(), -1, true);
264 content::WebContents* right_tab =
265 browser()->tab_strip_model()->GetActiveWebContents();
266 PermissionBubbleManager::FromWebContents(right_tab)
267 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
268 InfoBarResponder right_infobar_responder(
269 InfoBarService::FromWebContents(right_tab), InfoBarResponder::ACCEPT);
270 ui_test_utils::NavigateToURL(browser(), room_url);
272 ASSERT_TRUE(WaitForCallToComeUp(left_tab));
273 ASSERT_TRUE(WaitForCallToComeUp(right_tab));
275 ASSERT_TRUE(DetectRemoteVideoPlaying(left_tab));
276 ASSERT_TRUE(DetectRemoteVideoPlaying(right_tab));
278 chrome::CloseWebContents(browser(), left_tab, false);
279 chrome::CloseWebContents(browser(), right_tab, false);
282 #if defined(OS_LINUX)
283 #define MAYBE_MANUAL_FirefoxApprtcInteropTest MANUAL_FirefoxApprtcInteropTest
284 #else
285 // Not implemented yet on Windows and Mac.
286 #define MAYBE_MANUAL_FirefoxApprtcInteropTest DISABLED_MANUAL_FirefoxApprtcInteropTest
287 #endif
289 IN_PROC_BROWSER_TEST_F(WebRtcApprtcBrowserTest,
290 MAYBE_MANUAL_FirefoxApprtcInteropTest) {
291 // Disabled on Win XP: http://code.google.com/p/webrtc/issues/detail?id=2703.
292 if (OnWinXp())
293 return;
295 DetectErrorsInJavaScript();
296 ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost("9999"));
297 ASSERT_TRUE(LaunchColliderOnLocalHost("http://localhost:9999", "8089"));
298 while (!LocalApprtcInstanceIsUp())
299 DVLOG(1) << "Waiting for AppRTC to come up...";
301 GURL room_url = GURL("http://localhost:9999/r/some_room"
302 "?wshpp=localhost:8089&wstls=false"
303 "&firefox_fake_device=1");
304 chrome::AddTabAt(browser(), GURL(), -1, true);
305 content::WebContents* chrome_tab =
306 browser()->tab_strip_model()->GetActiveWebContents();
307 PermissionBubbleManager::FromWebContents(chrome_tab)
308 ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
309 InfoBarResponder infobar_responder(
310 InfoBarService::FromWebContents(chrome_tab), InfoBarResponder::ACCEPT);
311 ui_test_utils::NavigateToURL(browser(), room_url);
313 ASSERT_TRUE(LaunchFirefoxWithUrl(room_url));
315 ASSERT_TRUE(WaitForCallToComeUp(chrome_tab));
317 // Ensure Firefox manages to send video our way.
318 ASSERT_TRUE(DetectRemoteVideoPlaying(chrome_tab));