Chromium Code Reviews| 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 const mojom::MediaRouteProvider::CreateMediaRouteControllerCallback& cb) { | |
| 108 cb.Run(true); | |
| 109 } | |
| 110 | |
| 97 } // namespace | 111 } // namespace |
| 98 | 112 |
| 99 class RouteResponseCallbackHandler { | 113 class RouteResponseCallbackHandler { |
| 100 public: | 114 public: |
| 101 void Invoke(const RouteRequestResult& result) { | 115 void Invoke(const RouteRequestResult& result) { |
| 102 DoInvoke(result.route(), result.presentation_id(), result.error(), | 116 DoInvoke(result.route(), result.presentation_id(), result.error(), |
| 103 result.result_code()); | 117 result.result_code()); |
| 104 } | 118 } |
| 105 MOCK_METHOD4(DoInvoke, | 119 MOCK_METHOD4(DoInvoke, |
| 106 void(const MediaRoute* route, | 120 void(const MediaRoute* route, |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 738 sinks_observer.reset(); | 752 sinks_observer.reset(); |
| 739 extra_sinks_observer.reset(); | 753 extra_sinks_observer.reset(); |
| 740 unrelated_sinks_observer.reset(); | 754 unrelated_sinks_observer.reset(); |
| 741 cached_sinks_observer.reset(); | 755 cached_sinks_observer.reset(); |
| 742 cached_sinks_observer2.reset(); | 756 cached_sinks_observer2.reset(); |
| 743 run_loop2.Run(); | 757 run_loop2.Run(); |
| 744 } | 758 } |
| 745 | 759 |
| 746 TEST_F(MediaRouterMojoImplTest, | 760 TEST_F(MediaRouterMojoImplTest, |
| 747 RegisterMediaSinksObserverWithAvailabilityChange) { | 761 RegisterMediaSinksObserverWithAvailabilityChange) { |
| 748 | |
| 749 // When availability is UNAVAILABLE, no calls should be made to MRPM. | 762 // When availability is UNAVAILABLE, no calls should be made to MRPM. |
| 750 router()->OnSinkAvailabilityUpdated( | 763 router()->OnSinkAvailabilityUpdated( |
| 751 mojom::MediaRouter::SinkAvailability::UNAVAILABLE); | 764 mojom::MediaRouter::SinkAvailability::UNAVAILABLE); |
| 752 MediaSource media_source(kSource); | 765 MediaSource media_source(kSource); |
| 753 std::unique_ptr<MockMediaSinksObserver> sinks_observer( | 766 std::unique_ptr<MockMediaSinksObserver> sinks_observer( |
| 754 new MockMediaSinksObserver(router(), media_source, | 767 new MockMediaSinksObserver(router(), media_source, |
| 755 url::Origin(GURL(kOrigin)))); | 768 url::Origin(GURL(kOrigin)))); |
| 756 EXPECT_CALL(*sinks_observer, OnSinksReceived(IsEmpty())); | 769 EXPECT_CALL(*sinks_observer, OnSinksReceived(IsEmpty())); |
| 757 EXPECT_TRUE(sinks_observer->Init()); | 770 EXPECT_TRUE(sinks_observer->Init()); |
| 758 MediaSource media_source2(kSource2); | 771 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)); | 1188 EXPECT_CALL(mock_media_route_provider_, DetachRoute(kRouteId2)); |
| 1176 ConnectProviderManagerService(); | 1189 ConnectProviderManagerService(); |
| 1177 ProcessEventLoop(); | 1190 ProcessEventLoop(); |
| 1178 } | 1191 } |
| 1179 | 1192 |
| 1180 TEST_F(MediaRouterMojoImplTest, SearchSinks) { | 1193 TEST_F(MediaRouterMojoImplTest, SearchSinks) { |
| 1181 std::string search_input("input"); | 1194 std::string search_input("input"); |
| 1182 std::string domain("google.com"); | 1195 std::string domain("google.com"); |
| 1183 MediaSource media_source(kSource); | 1196 MediaSource media_source(kSource); |
| 1184 | 1197 |
| 1185 EXPECT_CALL( | 1198 EXPECT_CALL(mock_media_route_provider_, |
| 1186 mock_media_route_provider_, SearchSinks_(kSinkId, kSource, _, _)) | 1199 SearchSinksInternal(kSinkId, kSource, _, _)) |
| 1187 .WillOnce(Invoke([&search_input, &domain]( | 1200 .WillOnce( |
| 1188 const std::string& sink_id, const std::string& source, | 1201 Invoke([&search_input, &domain]( |
| 1189 const mojom::SinkSearchCriteriaPtr& search_criteria, | 1202 const std::string& sink_id, const std::string& source, |
| 1190 const mojom::MediaRouteProvider::SearchSinksCallback& cb) { | 1203 const mojom::SinkSearchCriteriaPtr& search_criteria, |
| 1191 EXPECT_EQ(search_input, search_criteria->input); | 1204 const mojom::MediaRouteProvider::SearchSinksCallback& cb) { |
| 1192 EXPECT_EQ(domain, search_criteria->domain); | 1205 EXPECT_EQ(search_input, search_criteria->input); |
| 1193 cb.Run(kSinkId2); | 1206 EXPECT_EQ(domain, search_criteria->domain); |
| 1194 })); | 1207 cb.Run(kSinkId2); |
| 1208 })); | |
| 1195 | 1209 |
| 1196 SinkResponseCallbackHandler sink_handler; | 1210 SinkResponseCallbackHandler sink_handler; |
| 1197 EXPECT_CALL(sink_handler, Invoke(kSinkId2)).Times(1); | 1211 EXPECT_CALL(sink_handler, Invoke(kSinkId2)).Times(1); |
| 1198 MediaSinkSearchResponseCallback sink_callback = base::Bind( | 1212 MediaSinkSearchResponseCallback sink_callback = base::Bind( |
| 1199 &SinkResponseCallbackHandler::Invoke, base::Unretained(&sink_handler)); | 1213 &SinkResponseCallbackHandler::Invoke, base::Unretained(&sink_handler)); |
| 1200 | 1214 |
| 1201 router()->SearchSinks(kSinkId, kSource, search_input, domain, sink_callback); | 1215 router()->SearchSinks(kSinkId, kSource, search_input, domain, sink_callback); |
| 1202 | 1216 |
| 1203 base::RunLoop run_loop; | 1217 base::RunLoop run_loop; |
| 1204 run_loop.RunUntilIdle(); | 1218 run_loop.RunUntilIdle(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1216 std::string provider_name = "cast"; | 1230 std::string provider_name = "cast"; |
| 1217 | 1231 |
| 1218 EXPECT_CALL(mock_media_route_provider_, ProvideSinks(provider_name, sinks)); | 1232 EXPECT_CALL(mock_media_route_provider_, ProvideSinks(provider_name, sinks)); |
| 1219 | 1233 |
| 1220 router()->ProvideSinks(provider_name, sinks); | 1234 router()->ProvideSinks(provider_name, sinks); |
| 1221 | 1235 |
| 1222 base::RunLoop run_loop; | 1236 base::RunLoop run_loop; |
| 1223 run_loop.RunUntilIdle(); | 1237 run_loop.RunUntilIdle(); |
| 1224 } | 1238 } |
| 1225 | 1239 |
| 1240 TEST_F(MediaRouterMojoImplTest, GetRouteController) { | |
| 1241 base::RunLoop run_loop1; | |
| 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( | |
| 1253 [&media_controller](const std::string& route_id, | |
| 1254 mojom::MediaControllerRequest& request, | |
| 1255 const mojom::MediaRouteProvider:: | |
| 1256 CreateMediaRouteControllerCallback& cb) { | |
| 1257 media_controller.Bind(std::move(request)); | |
| 1258 cb.Run(true); | |
| 1259 })); | |
| 1260 EXPECT_CALL(mock_media_route_provider_, | |
| 1261 SetMediaRouteStatusObserverInternal(kRouteId, _)) | |
| 1262 .WillOnce(Invoke([&route_controller_as_observer]( | |
| 1263 const std::string& route_id, | |
| 1264 mojom::MediaStatusObserverPtr& observer) { | |
| 1265 route_controller_as_observer = std::move(observer); | |
| 1266 })); | |
| 1267 // GetRouteController() should return a MediaRouteController that is connected | |
| 1268 // to the MediaController provided by the MediaRouteProvider, and will also be | |
| 1269 // subscribed to MediaStatus updates. | |
| 1270 scoped_refptr<MediaRouteController> route_controller = | |
| 1271 router()->GetRouteController(kRouteId); | |
| 1272 run_loop1.RunUntilIdle(); | |
| 1273 | |
| 1274 // Media commands sent to the MediaRouteController should be forwarded to the | |
| 1275 // MediaController created by the MediaRouteProvider. | |
| 1276 EXPECT_CALL(media_controller, Play()); | |
| 1277 route_controller->Play(); | |
| 1278 | |
| 1279 // Add an observer to the MediaRouteController. | |
| 1280 MockMediaRouteControllerObserver controller_observer(route_controller); | |
| 1281 | |
| 1282 base::RunLoop run_loop2; | |
|
dcheng
2017/04/14 05:30:08
Can this just use the original RunLoop from line 1
takumif
2017/04/14 18:43:00
How do I do that? I thought Run()/RunUntilIdle() c
| |
| 1283 | |
| 1284 // The MediaRouteController should be registered with the MediaRouteProvider | |
| 1285 // as a MediaStatusObserver, and should also notify its own observers. | |
| 1286 EXPECT_CALL(controller_observer, OnMediaStatusUpdated(media_status)); | |
| 1287 route_controller_as_observer->OnMediaStatusUpdated(media_status); | |
| 1288 | |
| 1289 run_loop2.RunUntilIdle(); | |
| 1290 } | |
| 1291 | |
| 1292 TEST_F(MediaRouterMojoImplTest, GetRouteControllerMultipleTimes) { | |
| 1293 base::RunLoop run_loop; | |
| 1294 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, | |
| 1295 std::string(), std::vector<std::string>()); | |
| 1296 | |
| 1297 EXPECT_CALL(mock_media_route_provider_, | |
| 1298 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1299 .WillOnce(Invoke(OnCreateMediaRouteController)); | |
| 1300 scoped_refptr<MediaRouteController> route_controller1a = | |
| 1301 router()->GetRouteController(kRouteId); | |
| 1302 | |
| 1303 // Calling GetRouteController() with the same route ID for the second time | |
| 1304 // (without destroying the MediaRouteController first) should not result in a | |
| 1305 // CreateMediaRouteController() call. | |
| 1306 scoped_refptr<MediaRouteController> route_controller1b = | |
| 1307 router()->GetRouteController(kRouteId); | |
| 1308 | |
| 1309 // The same MediaRouteController instance should have been returned. | |
| 1310 EXPECT_EQ(route_controller1a.get(), route_controller1b.get()); | |
| 1311 | |
| 1312 // Calling GetRouteController() with another route ID should result in a | |
| 1313 // CreateMediaRouteController() call. | |
| 1314 EXPECT_CALL(mock_media_route_provider_, | |
| 1315 CreateMediaRouteControllerInternal(kRouteId2, _, _)) | |
| 1316 .WillOnce(Invoke(OnCreateMediaRouteController)); | |
| 1317 scoped_refptr<MediaRouteController> route_controller2 = | |
| 1318 router()->GetRouteController(kRouteId2); | |
| 1319 | |
| 1320 run_loop.RunUntilIdle(); | |
| 1321 } | |
| 1322 | |
| 1323 TEST_F(MediaRouterMojoImplTest, GetRouteControllerAfterInvalidation) { | |
| 1324 base::RunLoop run_loop; | |
| 1325 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), | |
| 1326 std::vector<std::string>()); | |
| 1327 | |
| 1328 EXPECT_CALL(mock_media_route_provider_, | |
| 1329 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1330 .Times(2) | |
| 1331 .WillRepeatedly(Invoke(OnCreateMediaRouteController)); | |
| 1332 | |
| 1333 scoped_refptr<MediaRouteController> route_controller = | |
| 1334 router()->GetRouteController(kRouteId); | |
| 1335 // Invalidate the MediaRouteController. | |
| 1336 route_controller = nullptr; | |
| 1337 // Call again with the same route ID. Since we've invalidated the | |
| 1338 // MediaRouteController, CreateMediaRouteController() should be called again. | |
| 1339 route_controller = router()->GetRouteController(kRouteId); | |
| 1340 | |
| 1341 run_loop.RunUntilIdle(); | |
| 1342 } | |
| 1343 | |
| 1344 TEST_F(MediaRouterMojoImplTest, GetRouteControllerAfterRouteInvalidation) { | |
| 1345 base::RunLoop run_loop; | |
| 1346 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, | |
| 1347 std::string(), std::vector<std::string>()); | |
| 1348 | |
| 1349 EXPECT_CALL(mock_media_route_provider_, | |
| 1350 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1351 .WillOnce(Invoke(OnCreateMediaRouteController)); | |
| 1352 EXPECT_CALL(mock_media_route_provider_, | |
| 1353 CreateMediaRouteControllerInternal(kRouteId2, _, _)) | |
| 1354 .Times(2) | |
| 1355 .WillRepeatedly(Invoke(OnCreateMediaRouteController)); | |
| 1356 | |
| 1357 MockMediaRouteControllerObserver observer1a( | |
| 1358 router()->GetRouteController(kRouteId)); | |
| 1359 MockMediaRouteControllerObserver observer2a( | |
| 1360 router()->GetRouteController(kRouteId2)); | |
| 1361 | |
| 1362 // Update the routes list with |kRouteId| but without |kRouteId2|. This should | |
| 1363 // remove the controller for |kRouteId2|, resulting in | |
| 1364 // CreateMediaRouteController() getting called again for |kRouteId2| below. | |
| 1365 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), | |
| 1366 std::vector<std::string>()); | |
| 1367 // Add back |kRouteId2| so that a controller can be created for it. | |
| 1368 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, | |
| 1369 std::string(), std::vector<std::string>()); | |
| 1370 | |
| 1371 MockMediaRouteControllerObserver observer1b( | |
| 1372 router()->GetRouteController(kRouteId)); | |
| 1373 MockMediaRouteControllerObserver observer2b( | |
| 1374 router()->GetRouteController(kRouteId2)); | |
| 1375 | |
| 1376 run_loop.RunUntilIdle(); | |
| 1377 } | |
| 1378 | |
| 1379 TEST_F(MediaRouterMojoImplTest, FailToCreateRouteController) { | |
| 1380 base::RunLoop run_loop; | |
| 1381 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), | |
| 1382 std::vector<std::string>()); | |
| 1383 | |
| 1384 EXPECT_CALL(mock_media_route_provider_, | |
| 1385 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1386 .WillOnce(Invoke( | |
| 1387 [](Unused, Unused, | |
| 1388 const mojom::MediaRouteProvider:: | |
| 1389 CreateMediaRouteControllerCallback& cb) { cb.Run(false); })); | |
| 1390 MockMediaRouteControllerObserver observer( | |
| 1391 router()->GetRouteController(kRouteId)); | |
| 1392 | |
| 1393 // When the MediaRouter is notified that the MediaRouteProvider failed to | |
| 1394 // create a controller, the browser-side controller should be invalidated. | |
| 1395 EXPECT_CALL(observer, OnControllerInvalidated()); | |
| 1396 | |
| 1397 run_loop.RunUntilIdle(); | |
| 1398 } | |
| 1399 | |
| 1226 class MediaRouterMojoExtensionTest : public ::testing::Test { | 1400 class MediaRouterMojoExtensionTest : public ::testing::Test { |
| 1227 public: | 1401 public: |
| 1228 MediaRouterMojoExtensionTest() : process_manager_(nullptr) {} | 1402 MediaRouterMojoExtensionTest() : process_manager_(nullptr) {} |
| 1229 | 1403 |
| 1230 ~MediaRouterMojoExtensionTest() override {} | 1404 ~MediaRouterMojoExtensionTest() override {} |
| 1231 | 1405 |
| 1232 protected: | 1406 protected: |
| 1233 void SetUp() override { | 1407 void SetUp() override { |
| 1234 // Set the extension's version number to be identical to the browser's. | 1408 // Set the extension's version number to be identical to the browser's. |
| 1235 extension_ = | 1409 extension_ = |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1596 EXPECT_CALL(mock_media_route_provider_, | 1770 EXPECT_CALL(mock_media_route_provider_, |
| 1597 UpdateMediaSinks(MediaSourceForDesktop().id())) | 1771 UpdateMediaSinks(MediaSourceForDesktop().id())) |
| 1598 .WillOnce(InvokeWithoutArgs([&run_loop2]() { | 1772 .WillOnce(InvokeWithoutArgs([&run_loop2]() { |
| 1599 run_loop2.Quit(); | 1773 run_loop2.Quit(); |
| 1600 })); | 1774 })); |
| 1601 | 1775 |
| 1602 run_loop2.Run(); | 1776 run_loop2.Run(); |
| 1603 } | 1777 } |
| 1604 | 1778 |
| 1605 } // namespace media_router | 1779 } // namespace media_router |
| OLD | NEW |