| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 16 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
| 17 #include "base/run_loop.h" | 17 #include "base/run_loop.h" |
| 18 #include "base/synchronization/waitable_event.h" | |
| 19 #include "base/test/histogram_tester.h" | 18 #include "base/test/histogram_tester.h" |
| 20 #include "base/test/mock_callback.h" | 19 #include "base/test/mock_callback.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" | 20 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "chrome/browser/media/router/issue.h" | 21 #include "chrome/browser/media/router/issue.h" |
| 23 #include "chrome/browser/media/router/media_route.h" | 22 #include "chrome/browser/media/router/media_route.h" |
| 24 #include "chrome/browser/media/router/media_source_helper.h" | 23 #include "chrome/browser/media/router/media_source_helper.h" |
| 25 #include "chrome/browser/media/router/mock_media_router.h" | 24 #include "chrome/browser/media/router/mock_media_router.h" |
| 26 #include "chrome/browser/media/router/mojo/media_router_mojo_metrics.h" | 25 #include "chrome/browser/media/router/mojo/media_router_mojo_metrics.h" |
| 27 #include "chrome/browser/media/router/mojo/media_router_mojo_test.h" | 26 #include "chrome/browser/media/router/mojo/media_router_mojo_test.h" |
| 28 #include "chrome/browser/media/router/route_message.h" | 27 #include "chrome/browser/media/router/route_message.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 48 using testing::AtMost; | 47 using testing::AtMost; |
| 49 using testing::Eq; | 48 using testing::Eq; |
| 50 using testing::Invoke; | 49 using testing::Invoke; |
| 51 using testing::InvokeWithoutArgs; | 50 using testing::InvokeWithoutArgs; |
| 52 using testing::IsEmpty; | 51 using testing::IsEmpty; |
| 53 using testing::Mock; | 52 using testing::Mock; |
| 54 using testing::Not; | 53 using testing::Not; |
| 55 using testing::Pointee; | 54 using testing::Pointee; |
| 56 using testing::Return; | 55 using testing::Return; |
| 57 using testing::ReturnRef; | 56 using testing::ReturnRef; |
| 57 using testing::Unused; |
| 58 using testing::SaveArg; | 58 using testing::SaveArg; |
| 59 using testing::Sequence; | 59 using testing::Sequence; |
| 60 | 60 |
| 61 namespace media_router { | 61 namespace media_router { |
| 62 | 62 |
| 63 namespace { | 63 namespace { |
| 64 | 64 |
| 65 const char kDescription[] = "description"; | 65 const char kDescription[] = "description"; |
| 66 const char kError[] = "error"; | 66 const char kError[] = "error"; |
| 67 const char kMessage[] = "message"; | 67 const char kMessage[] = "message"; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 82 | 82 |
| 83 IssueInfo CreateIssueInfo(const std::string& title) { | 83 IssueInfo CreateIssueInfo(const std::string& title) { |
| 84 IssueInfo issue_info; | 84 IssueInfo issue_info; |
| 85 issue_info.title = title; | 85 issue_info.title = title; |
| 86 issue_info.message = std::string("msg"); | 86 issue_info.message = std::string("msg"); |
| 87 issue_info.default_action = IssueInfo::Action::DISMISS; | 87 issue_info.default_action = IssueInfo::Action::DISMISS; |
| 88 issue_info.severity = IssueInfo::Severity::WARNING; | 88 issue_info.severity = IssueInfo::Severity::WARNING; |
| 89 return issue_info; | 89 return issue_info; |
| 90 } | 90 } |
| 91 | 91 |
| 92 // Creates a media route whose ID is |kRouteId|. |
| 92 MediaRoute CreateMediaRoute() { | 93 MediaRoute CreateMediaRoute() { |
| 93 return MediaRoute(kRouteId, MediaSource(kSource), kSinkId, kDescription, true, | 94 return MediaRoute(kRouteId, MediaSource(kSource), kSinkId, kDescription, true, |
| 94 std::string(), true); | 95 std::string(), true); |
| 95 } | 96 } |
| 96 | 97 |
| 98 // Creates a media route whose ID is |kRouteId2|. |
| 99 MediaRoute CreateMediaRoute2() { |
| 100 return MediaRoute(kRouteId2, MediaSource(kSource), kSinkId, kDescription, |
| 101 true, std::string(), true); |
| 102 } |
| 103 |
| 104 void OnCreateMediaRouteController( |
| 105 Unused, |
| 106 Unused, |
| 107 Unused, |
| 108 const mojom::MediaRouteProvider::CreateMediaRouteControllerCallback& cb) { |
| 109 cb.Run(true); |
| 110 } |
| 111 |
| 97 } // namespace | 112 } // namespace |
| 98 | 113 |
| 99 class RouteResponseCallbackHandler { | 114 class RouteResponseCallbackHandler { |
| 100 public: | 115 public: |
| 101 void Invoke(const RouteRequestResult& result) { | 116 void Invoke(const RouteRequestResult& result) { |
| 102 DoInvoke(result.route(), result.presentation_id(), result.error(), | 117 DoInvoke(result.route(), result.presentation_id(), result.error(), |
| 103 result.result_code()); | 118 result.result_code()); |
| 104 } | 119 } |
| 105 MOCK_METHOD4(DoInvoke, | 120 MOCK_METHOD4(DoInvoke, |
| 106 void(const MediaRoute* route, | 121 void(const MediaRoute* route, |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 sinks_observer.reset(); | 753 sinks_observer.reset(); |
| 739 extra_sinks_observer.reset(); | 754 extra_sinks_observer.reset(); |
| 740 unrelated_sinks_observer.reset(); | 755 unrelated_sinks_observer.reset(); |
| 741 cached_sinks_observer.reset(); | 756 cached_sinks_observer.reset(); |
| 742 cached_sinks_observer2.reset(); | 757 cached_sinks_observer2.reset(); |
| 743 run_loop2.Run(); | 758 run_loop2.Run(); |
| 744 } | 759 } |
| 745 | 760 |
| 746 TEST_F(MediaRouterMojoImplTest, | 761 TEST_F(MediaRouterMojoImplTest, |
| 747 RegisterMediaSinksObserverWithAvailabilityChange) { | 762 RegisterMediaSinksObserverWithAvailabilityChange) { |
| 748 | |
| 749 // When availability is UNAVAILABLE, no calls should be made to MRPM. | 763 // When availability is UNAVAILABLE, no calls should be made to MRPM. |
| 750 router()->OnSinkAvailabilityUpdated( | 764 router()->OnSinkAvailabilityUpdated( |
| 751 mojom::MediaRouter::SinkAvailability::UNAVAILABLE); | 765 mojom::MediaRouter::SinkAvailability::UNAVAILABLE); |
| 752 MediaSource media_source(kSource); | 766 MediaSource media_source(kSource); |
| 753 std::unique_ptr<MockMediaSinksObserver> sinks_observer( | 767 std::unique_ptr<MockMediaSinksObserver> sinks_observer( |
| 754 new MockMediaSinksObserver(router(), media_source, | 768 new MockMediaSinksObserver(router(), media_source, |
| 755 url::Origin(GURL(kOrigin)))); | 769 url::Origin(GURL(kOrigin)))); |
| 756 EXPECT_CALL(*sinks_observer, OnSinksReceived(IsEmpty())); | 770 EXPECT_CALL(*sinks_observer, OnSinksReceived(IsEmpty())); |
| 757 EXPECT_TRUE(sinks_observer->Init()); | 771 EXPECT_TRUE(sinks_observer->Init()); |
| 758 MediaSource media_source2(kSource2); | 772 MediaSource media_source2(kSource2); |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 EXPECT_CALL(mock_media_route_provider_, DetachRoute(kRouteId2)); | 1189 EXPECT_CALL(mock_media_route_provider_, DetachRoute(kRouteId2)); |
| 1176 ConnectProviderManagerService(); | 1190 ConnectProviderManagerService(); |
| 1177 ProcessEventLoop(); | 1191 ProcessEventLoop(); |
| 1178 } | 1192 } |
| 1179 | 1193 |
| 1180 TEST_F(MediaRouterMojoImplTest, SearchSinks) { | 1194 TEST_F(MediaRouterMojoImplTest, SearchSinks) { |
| 1181 std::string search_input("input"); | 1195 std::string search_input("input"); |
| 1182 std::string domain("google.com"); | 1196 std::string domain("google.com"); |
| 1183 MediaSource media_source(kSource); | 1197 MediaSource media_source(kSource); |
| 1184 | 1198 |
| 1185 EXPECT_CALL( | 1199 EXPECT_CALL(mock_media_route_provider_, |
| 1186 mock_media_route_provider_, SearchSinks_(kSinkId, kSource, _, _)) | 1200 SearchSinksInternal(kSinkId, kSource, _, _)) |
| 1187 .WillOnce(Invoke([&search_input, &domain]( | 1201 .WillOnce( |
| 1188 const std::string& sink_id, const std::string& source, | 1202 Invoke([&search_input, &domain]( |
| 1189 const mojom::SinkSearchCriteriaPtr& search_criteria, | 1203 const std::string& sink_id, const std::string& source, |
| 1190 const mojom::MediaRouteProvider::SearchSinksCallback& cb) { | 1204 const mojom::SinkSearchCriteriaPtr& search_criteria, |
| 1191 EXPECT_EQ(search_input, search_criteria->input); | 1205 const mojom::MediaRouteProvider::SearchSinksCallback& cb) { |
| 1192 EXPECT_EQ(domain, search_criteria->domain); | 1206 EXPECT_EQ(search_input, search_criteria->input); |
| 1193 cb.Run(kSinkId2); | 1207 EXPECT_EQ(domain, search_criteria->domain); |
| 1194 })); | 1208 cb.Run(kSinkId2); |
| 1209 })); |
| 1195 | 1210 |
| 1196 SinkResponseCallbackHandler sink_handler; | 1211 SinkResponseCallbackHandler sink_handler; |
| 1197 EXPECT_CALL(sink_handler, Invoke(kSinkId2)).Times(1); | 1212 EXPECT_CALL(sink_handler, Invoke(kSinkId2)).Times(1); |
| 1198 MediaSinkSearchResponseCallback sink_callback = base::Bind( | 1213 MediaSinkSearchResponseCallback sink_callback = base::Bind( |
| 1199 &SinkResponseCallbackHandler::Invoke, base::Unretained(&sink_handler)); | 1214 &SinkResponseCallbackHandler::Invoke, base::Unretained(&sink_handler)); |
| 1200 | 1215 |
| 1201 router()->SearchSinks(kSinkId, kSource, search_input, domain, sink_callback); | 1216 router()->SearchSinks(kSinkId, kSource, search_input, domain, sink_callback); |
| 1202 | 1217 |
| 1203 base::RunLoop run_loop; | 1218 base::RunLoop run_loop; |
| 1204 run_loop.RunUntilIdle(); | 1219 run_loop.RunUntilIdle(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1216 std::string provider_name = "cast"; | 1231 std::string provider_name = "cast"; |
| 1217 | 1232 |
| 1218 EXPECT_CALL(mock_media_route_provider_, ProvideSinks(provider_name, sinks)); | 1233 EXPECT_CALL(mock_media_route_provider_, ProvideSinks(provider_name, sinks)); |
| 1219 | 1234 |
| 1220 router()->ProvideSinks(provider_name, sinks); | 1235 router()->ProvideSinks(provider_name, sinks); |
| 1221 | 1236 |
| 1222 base::RunLoop run_loop; | 1237 base::RunLoop run_loop; |
| 1223 run_loop.RunUntilIdle(); | 1238 run_loop.RunUntilIdle(); |
| 1224 } | 1239 } |
| 1225 | 1240 |
| 1241 TEST_F(MediaRouterMojoImplTest, GetRouteController) { |
| 1242 MockMediaController media_controller; |
| 1243 mojom::MediaStatusObserverPtr route_controller_as_observer; |
| 1244 MediaStatus media_status; |
| 1245 media_status.title = "test title"; |
| 1246 |
| 1247 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), |
| 1248 std::vector<std::string>()); |
| 1249 |
| 1250 EXPECT_CALL(mock_media_route_provider_, |
| 1251 CreateMediaRouteControllerInternal(kRouteId, _, _, _)) |
| 1252 .WillOnce(Invoke([&media_controller, &route_controller_as_observer]( |
| 1253 const std::string& route_id, |
| 1254 mojom::MediaControllerRequest& request, |
| 1255 mojom::MediaStatusObserverPtr& observer, |
| 1256 const mojom::MediaRouteProvider:: |
| 1257 CreateMediaRouteControllerCallback& cb) { |
| 1258 media_controller.Bind(std::move(request)); |
| 1259 route_controller_as_observer = std::move(observer); |
| 1260 cb.Run(true); |
| 1261 })); |
| 1262 // GetRouteController() should return a MediaRouteController that is connected |
| 1263 // to the MediaController provided by the MediaRouteProvider, and will also be |
| 1264 // subscribed to MediaStatus updates. |
| 1265 scoped_refptr<MediaRouteController> route_controller = |
| 1266 router()->GetRouteController(kRouteId); |
| 1267 base::RunLoop().RunUntilIdle(); |
| 1268 |
| 1269 // Media commands sent to the MediaRouteController should be forwarded to the |
| 1270 // MediaController created by the MediaRouteProvider. |
| 1271 EXPECT_CALL(media_controller, Play()); |
| 1272 route_controller->Play(); |
| 1273 |
| 1274 // Add an observer to the MediaRouteController. |
| 1275 MockMediaRouteControllerObserver controller_observer(route_controller); |
| 1276 |
| 1277 // The MediaRouteController should be registered with the MediaRouteProvider |
| 1278 // as a MediaStatusObserver, and should also notify its own observers. |
| 1279 EXPECT_CALL(controller_observer, OnMediaStatusUpdated(media_status)); |
| 1280 route_controller_as_observer->OnMediaStatusUpdated(media_status); |
| 1281 |
| 1282 base::RunLoop().RunUntilIdle(); |
| 1283 } |
| 1284 |
| 1285 TEST_F(MediaRouterMojoImplTest, GetRouteControllerMultipleTimes) { |
| 1286 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, |
| 1287 std::string(), std::vector<std::string>()); |
| 1288 |
| 1289 EXPECT_CALL(mock_media_route_provider_, |
| 1290 CreateMediaRouteControllerInternal(kRouteId, _, _, _)) |
| 1291 .WillOnce(Invoke(OnCreateMediaRouteController)); |
| 1292 scoped_refptr<MediaRouteController> route_controller1a = |
| 1293 router()->GetRouteController(kRouteId); |
| 1294 |
| 1295 // Calling GetRouteController() with the same route ID for the second time |
| 1296 // (without destroying the MediaRouteController first) should not result in a |
| 1297 // CreateMediaRouteController() call. |
| 1298 scoped_refptr<MediaRouteController> route_controller1b = |
| 1299 router()->GetRouteController(kRouteId); |
| 1300 |
| 1301 // The same MediaRouteController instance should have been returned. |
| 1302 EXPECT_EQ(route_controller1a.get(), route_controller1b.get()); |
| 1303 |
| 1304 // Calling GetRouteController() with another route ID should result in a |
| 1305 // CreateMediaRouteController() call. |
| 1306 EXPECT_CALL(mock_media_route_provider_, |
| 1307 CreateMediaRouteControllerInternal(kRouteId2, _, _, _)) |
| 1308 .WillOnce(Invoke(OnCreateMediaRouteController)); |
| 1309 scoped_refptr<MediaRouteController> route_controller2 = |
| 1310 router()->GetRouteController(kRouteId2); |
| 1311 |
| 1312 base::RunLoop().RunUntilIdle(); |
| 1313 } |
| 1314 |
| 1315 TEST_F(MediaRouterMojoImplTest, GetRouteControllerAfterInvalidation) { |
| 1316 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), |
| 1317 std::vector<std::string>()); |
| 1318 |
| 1319 EXPECT_CALL(mock_media_route_provider_, |
| 1320 CreateMediaRouteControllerInternal(kRouteId, _, _, _)) |
| 1321 .Times(2) |
| 1322 .WillRepeatedly(Invoke(OnCreateMediaRouteController)); |
| 1323 |
| 1324 scoped_refptr<MediaRouteController> route_controller = |
| 1325 router()->GetRouteController(kRouteId); |
| 1326 // Invalidate the MediaRouteController. |
| 1327 route_controller = nullptr; |
| 1328 // Call again with the same route ID. Since we've invalidated the |
| 1329 // MediaRouteController, CreateMediaRouteController() should be called again. |
| 1330 route_controller = router()->GetRouteController(kRouteId); |
| 1331 |
| 1332 base::RunLoop().RunUntilIdle(); |
| 1333 } |
| 1334 |
| 1335 TEST_F(MediaRouterMojoImplTest, GetRouteControllerAfterRouteInvalidation) { |
| 1336 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, |
| 1337 std::string(), std::vector<std::string>()); |
| 1338 |
| 1339 EXPECT_CALL(mock_media_route_provider_, |
| 1340 CreateMediaRouteControllerInternal(kRouteId, _, _, _)) |
| 1341 .WillOnce(Invoke(OnCreateMediaRouteController)); |
| 1342 EXPECT_CALL(mock_media_route_provider_, |
| 1343 CreateMediaRouteControllerInternal(kRouteId2, _, _, _)) |
| 1344 .Times(2) |
| 1345 .WillRepeatedly(Invoke(OnCreateMediaRouteController)); |
| 1346 |
| 1347 MockMediaRouteControllerObserver observer1a( |
| 1348 router()->GetRouteController(kRouteId)); |
| 1349 MockMediaRouteControllerObserver observer2a( |
| 1350 router()->GetRouteController(kRouteId2)); |
| 1351 |
| 1352 // Update the routes list with |kRouteId| but without |kRouteId2|. This should |
| 1353 // remove the controller for |kRouteId2|, resulting in |
| 1354 // CreateMediaRouteController() getting called again for |kRouteId2| below. |
| 1355 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), |
| 1356 std::vector<std::string>()); |
| 1357 // Add back |kRouteId2| so that a controller can be created for it. |
| 1358 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, |
| 1359 std::string(), std::vector<std::string>()); |
| 1360 |
| 1361 MockMediaRouteControllerObserver observer1b( |
| 1362 router()->GetRouteController(kRouteId)); |
| 1363 MockMediaRouteControllerObserver observer2b( |
| 1364 router()->GetRouteController(kRouteId2)); |
| 1365 |
| 1366 base::RunLoop().RunUntilIdle(); |
| 1367 } |
| 1368 |
| 1369 TEST_F(MediaRouterMojoImplTest, FailToCreateRouteController) { |
| 1370 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), |
| 1371 std::vector<std::string>()); |
| 1372 |
| 1373 EXPECT_CALL(mock_media_route_provider_, |
| 1374 CreateMediaRouteControllerInternal(kRouteId, _, _, _)) |
| 1375 .WillOnce(Invoke( |
| 1376 [](Unused, Unused, Unused, |
| 1377 const mojom::MediaRouteProvider:: |
| 1378 CreateMediaRouteControllerCallback& cb) { cb.Run(false); })); |
| 1379 MockMediaRouteControllerObserver observer( |
| 1380 router()->GetRouteController(kRouteId)); |
| 1381 |
| 1382 // When the MediaRouter is notified that the MediaRouteProvider failed to |
| 1383 // create a controller, the browser-side controller should be invalidated. |
| 1384 EXPECT_CALL(observer, OnControllerInvalidated()); |
| 1385 |
| 1386 base::RunLoop().RunUntilIdle(); |
| 1387 } |
| 1388 |
| 1226 class MediaRouterMojoExtensionTest : public ::testing::Test { | 1389 class MediaRouterMojoExtensionTest : public ::testing::Test { |
| 1227 public: | 1390 public: |
| 1228 MediaRouterMojoExtensionTest() : process_manager_(nullptr) {} | 1391 MediaRouterMojoExtensionTest() : process_manager_(nullptr) {} |
| 1229 | 1392 |
| 1230 ~MediaRouterMojoExtensionTest() override {} | 1393 ~MediaRouterMojoExtensionTest() override {} |
| 1231 | 1394 |
| 1232 protected: | 1395 protected: |
| 1233 void SetUp() override { | 1396 void SetUp() override { |
| 1234 // Set the extension's version number to be identical to the browser's. | 1397 // Set the extension's version number to be identical to the browser's. |
| 1235 extension_ = | 1398 extension_ = |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1596 EXPECT_CALL(mock_media_route_provider_, | 1759 EXPECT_CALL(mock_media_route_provider_, |
| 1597 UpdateMediaSinks(MediaSourceForDesktop().id())) | 1760 UpdateMediaSinks(MediaSourceForDesktop().id())) |
| 1598 .WillOnce(InvokeWithoutArgs([&run_loop2]() { | 1761 .WillOnce(InvokeWithoutArgs([&run_loop2]() { |
| 1599 run_loop2.Quit(); | 1762 run_loop2.Quit(); |
| 1600 })); | 1763 })); |
| 1601 | 1764 |
| 1602 run_loop2.Run(); | 1765 run_loop2.Run(); |
| 1603 } | 1766 } |
| 1604 | 1767 |
| 1605 } // namespace media_router | 1768 } // namespace media_router |
| OLD | NEW |