1 // Copyright 2015 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 "chrome/test/media_router/media_router_integration_browsertest.h"
8 #include "base/files/file_util.h"
9 #include "base/json/json_file_value_serializer.h"
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/path_service.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/browser/ui/views/frame/browser_view.h"
19 #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "content/public/test/test_navigation_observer.h"
24 #include "content/public/test/test_utils.h"
25 #include "net/base/filename_util.h"
26 #include "testing/gtest/include/gtest/gtest.h"
29 namespace media_router
{
32 // The path relative to <chromium src>/out/<build config> for media router
33 // browser test resources.
34 const base::FilePath::StringPieceType kResourcePath
= FILE_PATH_LITERAL(
35 "media_router/browser_test_resources/");
36 // The javascript snippets.
37 const std::string kCheckSessionScript
= "checkSession();";
38 const std::string kCheckSessionFailedScript
= "checkSessionFailedToStart();";
39 const std::string kStartSessionScript
= "startSession();";
40 const std::string kStopSessionScript
= "stopSession()";
41 const std::string kWaitDeviceScript
= "waitUntilDeviceAvailable();";
43 void GetStartedSessionId(content::WebContents
* web_contents
,
44 std::string
* session_id
) {
45 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
46 web_contents
, "window.domAutomationController.send(startedSession.id)",
52 MediaRouterIntegrationBrowserTest::MediaRouterIntegrationBrowserTest() {
55 MediaRouterIntegrationBrowserTest::~MediaRouterIntegrationBrowserTest() {
58 void MediaRouterIntegrationBrowserTest::TearDownOnMainThread() {
59 MediaRouterBaseBrowserTest::TearDownOnMainThread();
60 test_navigation_observer_
.reset();
63 void MediaRouterIntegrationBrowserTest::ExecuteJavaScriptAPI(
64 content::WebContents
* web_contents
,
65 const std::string
& script
) {
66 std::string
result(ExecuteScriptAndExtractString(web_contents
, script
));
68 // Read the test result, the test result set by javascript is a
69 // JSON string with the following format:
70 // {"passed": "<true/false>", "errorMessage": "<error_message>"}
71 scoped_ptr
<base::Value
> value
=
72 base::JSONReader::Read(result
, base::JSON_ALLOW_TRAILING_COMMAS
);
74 // Convert to dictionary.
75 base::DictionaryValue
* dict_value
= nullptr;
76 ASSERT_TRUE(value
->GetAsDictionary(&dict_value
));
78 // Extract the fields.
80 ASSERT_TRUE(dict_value
->GetBoolean("passed", &passed
));
81 std::string error_message
;
82 ASSERT_TRUE(dict_value
->GetString("errorMessage", &error_message
));
84 ASSERT_TRUE(passed
) << error_message
;
87 void MediaRouterIntegrationBrowserTest::OpenTestPage(
88 base::FilePath::StringPieceType file_name
) {
89 base::FilePath full_path
= GetResourceFile(file_name
);
90 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(full_path
));
93 void MediaRouterIntegrationBrowserTest::OpenTestPageInNewTab(
94 base::FilePath::StringPieceType file_name
) {
95 base::FilePath full_path
= GetResourceFile(file_name
);
96 ui_test_utils::NavigateToURLWithDisposition(
97 browser(), net::FilePathToFileURL(full_path
), NEW_FOREGROUND_TAB
,
98 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
101 void MediaRouterIntegrationBrowserTest::StartSession(
102 content::WebContents
* web_contents
) {
103 test_navigation_observer_
.reset(
104 new content::TestNavigationObserver(web_contents
, 1));
105 test_navigation_observer_
->StartWatchingNewWebContents();
106 ExecuteJavaScriptAPI(web_contents
, kStartSessionScript
);
107 test_navigation_observer_
->Wait();
108 test_navigation_observer_
->StopWatchingNewWebContents();
111 void MediaRouterIntegrationBrowserTest::ChooseSink(
112 content::WebContents
* web_contents
,
113 const std::string
& sink_id
,
114 const std::string
& current_route
) {
115 content::WebContents
* dialog_contents
= GetMRDialog(web_contents
);
117 if (current_route
.empty()) {
120 route
= current_route
;
121 std::string script
= base::StringPrintf(
122 "window.document.getElementById('media-router-container')."
123 "currentRoute_ = %s", route
.c_str());
124 ASSERT_TRUE(content::ExecuteScript(dialog_contents
, script
));
126 std::string script
= base::StringPrintf(
127 "window.document.getElementById('media-router-container')."
128 "showOrCreateRoute_({'id': '%s', 'name': ''}, %s)",
129 sink_id
.c_str(), route
.c_str());
130 ASSERT_TRUE(content::ExecuteScript(dialog_contents
, script
));
133 content::WebContents
* MediaRouterIntegrationBrowserTest::GetMRDialog(
134 content::WebContents
* web_contents
) {
135 MediaRouterDialogControllerImpl
* controller
=
136 MediaRouterDialogControllerImpl::GetOrCreateForWebContents(web_contents
);
137 content::WebContents
* dialog_contents
= controller
->GetMediaRouterDialog();
138 CHECK(dialog_contents
);
139 return dialog_contents
;
142 void MediaRouterIntegrationBrowserTest::SetTestData(
143 base::FilePath::StringPieceType test_data_file
) {
144 base::FilePath full_path
= GetResourceFile(test_data_file
);
145 JSONFileValueDeserializer
deserializer(full_path
);
147 std::string error_message
;
148 scoped_ptr
<base::Value
> value(
149 deserializer
.Deserialize(&error_code
, &error_message
));
150 CHECK(value
.get()) << "Deserialize failed: " << error_message
;
151 std::string test_data_str
;
152 ASSERT_TRUE(base::JSONWriter::Write(*value
, &test_data_str
));
153 ExecuteScriptInBackgroundPageNoWait(
155 base::StringPrintf("localStorage['testdata'] = '%s'",
156 test_data_str
.c_str()));
159 content::WebContents
* MediaRouterIntegrationBrowserTest::OpenMRDialog(
160 content::WebContents
* web_contents
) {
161 MediaRouterDialogControllerImpl
* controller
=
162 MediaRouterDialogControllerImpl::GetOrCreateForWebContents(web_contents
);
163 test_navigation_observer_
.reset(
164 new content::TestNavigationObserver(web_contents
, 1));
165 test_navigation_observer_
->StartWatchingNewWebContents();
166 CHECK(controller
->ShowMediaRouterDialog());
167 test_navigation_observer_
->Wait();
168 test_navigation_observer_
->StopWatchingNewWebContents();
169 content::WebContents
* dialog_contents
= controller
->GetMediaRouterDialog();
170 CHECK(dialog_contents
);
171 return dialog_contents
;
174 base::FilePath
MediaRouterIntegrationBrowserTest::GetResourceFile(
175 base::FilePath::StringPieceType relative_path
) const {
176 base::FilePath base_dir
;
177 // ASSERT_TRUE can only be used in void returning functions.
178 // Use CHECK instead in non-void returning functions.
179 CHECK(PathService::Get(base::DIR_MODULE
, &base_dir
));
180 base::FilePath full_path
=
181 base_dir
.Append(kResourcePath
).Append(relative_path
);
182 CHECK(PathExists(full_path
));
186 int MediaRouterIntegrationBrowserTest::ExecuteScriptAndExtractInt(
187 const content::ToRenderFrameHost
& adapter
, const std::string
& script
) {
189 CHECK(content::ExecuteScriptAndExtractInt(adapter
, script
, &result
));
193 std::string
MediaRouterIntegrationBrowserTest::ExecuteScriptAndExtractString(
194 const content::ToRenderFrameHost
& adapter
, const std::string
& script
) {
196 CHECK(content::ExecuteScriptAndExtractString(adapter
, script
, &result
));
200 bool MediaRouterIntegrationBrowserTest::IsRouteCreatedOnUI() {
201 content::WebContents
* web_contents
=
202 browser()->tab_strip_model()->GetActiveWebContents();
203 content::WebContents
* dialog_contents
= GetMRDialog(web_contents
);
205 script
= base::StringPrintf(
206 "domAutomationController.send(window.document.getElementById("
207 "'media-router-container').routeList.length)");
208 return ExecuteScriptAndExtractInt(dialog_contents
, script
) == 1;
211 void MediaRouterIntegrationBrowserTest::WaitUntilRouteCreated() {
213 base::TimeDelta::FromSeconds(10), base::TimeDelta::FromSeconds(1),
214 base::Bind(&MediaRouterIntegrationBrowserTest::IsRouteCreatedOnUI
,
215 base::Unretained(this)));
218 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest
, MANUAL_Basic
) {
219 OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
220 content::WebContents
* web_contents
=
221 browser()->tab_strip_model()->GetActiveWebContents();
222 ASSERT_TRUE(web_contents
);
223 ExecuteJavaScriptAPI(web_contents
, kWaitDeviceScript
);
224 StartSession(web_contents
);
225 ChooseSink(web_contents
, "id1", "");
226 ExecuteJavaScriptAPI(web_contents
, kCheckSessionScript
);
227 Wait(base::TimeDelta::FromSeconds(5));
228 ExecuteJavaScriptAPI(web_contents
, kStopSessionScript
);
231 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest
,
232 MANUAL_Fail_No_Provider
) {
233 SetTestData(FILE_PATH_LITERAL("no_provider.json"));
234 OpenTestPage(FILE_PATH_LITERAL("no_provider.html"));
235 content::WebContents
* web_contents
=
236 browser()->tab_strip_model()->GetActiveWebContents();
237 ASSERT_TRUE(web_contents
);
238 ExecuteJavaScriptAPI(web_contents
, kWaitDeviceScript
);
239 StartSession(web_contents
);
240 ChooseSink(web_contents
, "id1", "");
241 ExecuteJavaScriptAPI(web_contents
, kCheckSessionFailedScript
);
244 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest
,
245 MANUAL_Fail_Create_Route
) {
246 SetTestData(FILE_PATH_LITERAL("fail_create_route.json"));
247 OpenTestPage(FILE_PATH_LITERAL("fail_create_route.html"));
248 content::WebContents
* web_contents
=
249 browser()->tab_strip_model()->GetActiveWebContents();
250 ASSERT_TRUE(web_contents
);
251 ExecuteJavaScriptAPI(web_contents
, kWaitDeviceScript
);
252 StartSession(web_contents
);
253 ChooseSink(web_contents
, "id1", "");
254 ExecuteJavaScriptAPI(web_contents
, kCheckSessionFailedScript
);
257 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest
, MANUAL_JoinSession
) {
258 OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
259 content::WebContents
* web_contents
=
260 browser()->tab_strip_model()->GetActiveWebContents();
261 ASSERT_TRUE(web_contents
);
262 ExecuteJavaScriptAPI(web_contents
, kWaitDeviceScript
);
263 StartSession(web_contents
);
264 ChooseSink(web_contents
, "id1", "");
265 ExecuteJavaScriptAPI(web_contents
, kCheckSessionScript
);
266 std::string session_id
;
267 GetStartedSessionId(web_contents
, &session_id
);
269 OpenTestPageInNewTab(FILE_PATH_LITERAL("basic_test.html"));
270 content::WebContents
* new_web_contents
=
271 browser()->tab_strip_model()->GetActiveWebContents();
272 ASSERT_TRUE(new_web_contents
);
273 ASSERT_NE(web_contents
, new_web_contents
);
274 ExecuteJavaScriptAPI(
276 base::StringPrintf("joinSession('%s');", session_id
.c_str()));
277 std::string joined_session_id
;
278 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
279 new_web_contents
, "window.domAutomationController.send(joinedSession.id)",
280 &joined_session_id
));
281 ASSERT_EQ(session_id
, joined_session_id
);
284 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest
,
285 MANUAL_Fail_JoinSession
) {
286 OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
287 content::WebContents
* web_contents
=
288 browser()->tab_strip_model()->GetActiveWebContents();
289 ASSERT_TRUE(web_contents
);
290 ExecuteJavaScriptAPI(web_contents
, kWaitDeviceScript
);
291 content::TestNavigationObserver
test_navigation_observer(web_contents
, 1);
292 StartSession(web_contents
);
293 ChooseSink(web_contents
, "id1", "");
294 ExecuteJavaScriptAPI(web_contents
, kCheckSessionScript
);
295 std::string session_id
;
296 GetStartedSessionId(web_contents
, &session_id
);
298 SetTestData(FILE_PATH_LITERAL("fail_join_session.json"));
299 OpenTestPage(FILE_PATH_LITERAL("fail_join_session.html"));
300 content::WebContents
* new_web_contents
=
301 browser()->tab_strip_model()->GetActiveWebContents();
302 ASSERT_TRUE(new_web_contents
);
303 ExecuteJavaScriptAPI(
305 base::StringPrintf("checkJoinSessionFails('%s');", session_id
.c_str()));
308 } // namespace media_router