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