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" | 18 #include "base/synchronization/waitable_event.h" |
|
imcheng
2017/04/07 22:45:48
#include not needed?
takumif
2017/04/11 04:08:37
Removed.
| |
| 19 #include "base/test/histogram_tester.h" | 19 #include "base/test/histogram_tester.h" |
| 20 #include "base/test/mock_callback.h" | 20 #include "base/test/mock_callback.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" | 21 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "chrome/browser/media/router/issue.h" | 22 #include "chrome/browser/media/router/issue.h" |
| 23 #include "chrome/browser/media/router/media_route.h" | 23 #include "chrome/browser/media/router/media_route.h" |
| 24 #include "chrome/browser/media/router/media_source_helper.h" | 24 #include "chrome/browser/media/router/media_source_helper.h" |
| 25 #include "chrome/browser/media/router/mock_media_router.h" | 25 #include "chrome/browser/media/router/mock_media_router.h" |
| 26 #include "chrome/browser/media/router/mojo/media_router_mojo_metrics.h" | 26 #include "chrome/browser/media/router/mojo/media_router_mojo_metrics.h" |
| 27 #include "chrome/browser/media/router/mojo/media_router_mojo_test.h" | 27 #include "chrome/browser/media/router/mojo/media_router_mojo_test.h" |
| 28 #include "chrome/browser/media/router/route_message.h" | 28 #include "chrome/browser/media/router/route_message.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 48 using testing::AtMost; | 48 using testing::AtMost; |
| 49 using testing::Eq; | 49 using testing::Eq; |
| 50 using testing::Invoke; | 50 using testing::Invoke; |
| 51 using testing::InvokeWithoutArgs; | 51 using testing::InvokeWithoutArgs; |
| 52 using testing::IsEmpty; | 52 using testing::IsEmpty; |
| 53 using testing::Mock; | 53 using testing::Mock; |
| 54 using testing::Not; | 54 using testing::Not; |
| 55 using testing::Pointee; | 55 using testing::Pointee; |
| 56 using testing::Return; | 56 using testing::Return; |
| 57 using testing::ReturnRef; | 57 using testing::ReturnRef; |
| 58 using testing::Unused; | |
| 58 using testing::SaveArg; | 59 using testing::SaveArg; |
| 59 using testing::Sequence; | 60 using testing::Sequence; |
| 60 | 61 |
| 61 namespace media_router { | 62 namespace media_router { |
| 62 | 63 |
| 63 namespace { | 64 namespace { |
| 64 | 65 |
| 65 const char kDescription[] = "description"; | 66 const char kDescription[] = "description"; |
| 66 const char kError[] = "error"; | 67 const char kError[] = "error"; |
| 67 const char kMessage[] = "message"; | 68 const char kMessage[] = "message"; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 82 | 83 |
| 83 IssueInfo CreateIssueInfo(const std::string& title) { | 84 IssueInfo CreateIssueInfo(const std::string& title) { |
| 84 IssueInfo issue_info; | 85 IssueInfo issue_info; |
| 85 issue_info.title = title; | 86 issue_info.title = title; |
| 86 issue_info.message = std::string("msg"); | 87 issue_info.message = std::string("msg"); |
| 87 issue_info.default_action = IssueInfo::Action::DISMISS; | 88 issue_info.default_action = IssueInfo::Action::DISMISS; |
| 88 issue_info.severity = IssueInfo::Severity::WARNING; | 89 issue_info.severity = IssueInfo::Severity::WARNING; |
| 89 return issue_info; | 90 return issue_info; |
| 90 } | 91 } |
| 91 | 92 |
| 93 // Creates a media route whose ID is |kRouteId|. | |
| 92 MediaRoute CreateMediaRoute() { | 94 MediaRoute CreateMediaRoute() { |
| 93 return MediaRoute(kRouteId, MediaSource(kSource), kSinkId, kDescription, true, | 95 return MediaRoute(kRouteId, MediaSource(kSource), kSinkId, kDescription, true, |
| 94 std::string(), true); | 96 std::string(), true); |
| 95 } | 97 } |
| 96 | 98 |
| 99 // Creates a media route whose ID is |kRouteId2|. | |
| 100 MediaRoute CreateMediaRoute2() { | |
| 101 return MediaRoute(kRouteId2, MediaSource(kSource), kSinkId, kDescription, | |
| 102 true, std::string(), true); | |
| 103 } | |
| 104 | |
| 105 void OnCreateMediaRouteController( | |
| 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 base::RunLoop run_loop1; | |
| 1243 MockMediaController media_controller; | |
| 1244 mojom::MediaStatusObserverPtr route_controller_as_observer; | |
| 1245 MediaStatus media_status; | |
| 1246 media_status.title = "test title"; | |
| 1247 | |
| 1248 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), | |
| 1249 std::vector<std::string>()); | |
| 1250 | |
| 1251 EXPECT_CALL(mock_media_route_provider_, | |
| 1252 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1253 .WillOnce(Invoke( | |
| 1254 [&media_controller](const std::string& route_id, | |
| 1255 mojom::MediaControllerRequest& request, | |
| 1256 const mojom::MediaRouteProvider:: | |
| 1257 CreateMediaRouteControllerCallback& cb) { | |
| 1258 media_controller.Bind(std::move(request)); | |
| 1259 cb.Run(true); | |
| 1260 })); | |
| 1261 EXPECT_CALL(mock_media_route_provider_, | |
| 1262 SetMediaRouteStatusObserverInternal(kRouteId, _)) | |
| 1263 .WillOnce(Invoke([&route_controller_as_observer]( | |
| 1264 const std::string& route_id, | |
| 1265 mojom::MediaStatusObserverPtr& observer) { | |
| 1266 route_controller_as_observer = std::move(observer); | |
| 1267 })); | |
| 1268 // GetRouteController() should return a MediaRouteController that is connected | |
| 1269 // to the MediaController provided by the MediaRouteProvider, and will also be | |
| 1270 // subscribed to MediaStatus updates. | |
| 1271 scoped_refptr<MediaRouteController> route_controller = | |
| 1272 router()->GetRouteController(kRouteId); | |
| 1273 run_loop1.RunUntilIdle(); | |
| 1274 | |
| 1275 // Media commands sent to the MediaRouteController should be forwarded to the | |
| 1276 // MediaController created by the MediaRouteProvider. | |
| 1277 EXPECT_CALL(media_controller, Play()); | |
| 1278 route_controller->Play(); | |
| 1279 | |
| 1280 // Add an observer to the MediaRouteController. | |
| 1281 MockMediaRouteControllerObserver controller_observer(route_controller); | |
| 1282 | |
| 1283 base::RunLoop run_loop2; | |
| 1284 | |
| 1285 // The MediaRouteController should be registered with the MediaRouteProvider | |
| 1286 // as a MediaStatusObserver, and should also notify its own observers. | |
| 1287 EXPECT_CALL(controller_observer, OnMediaStatusUpdated(media_status)); | |
| 1288 route_controller_as_observer->OnMediaStatusUpdated(media_status); | |
| 1289 | |
| 1290 run_loop2.RunUntilIdle(); | |
| 1291 } | |
| 1292 | |
| 1293 TEST_F(MediaRouterMojoImplTest, GetRouteControllerMultipleTimes) { | |
| 1294 base::RunLoop run_loop; | |
| 1295 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, | |
| 1296 std::string(), std::vector<std::string>()); | |
| 1297 | |
| 1298 EXPECT_CALL(mock_media_route_provider_, | |
| 1299 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1300 .WillOnce(Invoke(OnCreateMediaRouteController)); | |
| 1301 scoped_refptr<MediaRouteController> route_controller1a = | |
| 1302 router()->GetRouteController(kRouteId); | |
| 1303 | |
| 1304 // Calling GetRouteController() with the same route ID for the second time | |
| 1305 // (without destroying the MediaRouteController first) should not result in a | |
| 1306 // CreateMediaRouteController() call. | |
| 1307 scoped_refptr<MediaRouteController> route_controller1b = | |
| 1308 router()->GetRouteController(kRouteId); | |
| 1309 | |
| 1310 // The same MediaRouteController instance should have been returned. | |
| 1311 EXPECT_EQ(route_controller1a.get(), route_controller1b.get()); | |
| 1312 | |
| 1313 // Calling GetRouteController() with another route ID should result in a | |
| 1314 // CreateMediaRouteController() call. | |
| 1315 EXPECT_CALL(mock_media_route_provider_, | |
| 1316 CreateMediaRouteControllerInternal(kRouteId2, _, _)) | |
| 1317 .WillOnce(Invoke(OnCreateMediaRouteController)); | |
| 1318 scoped_refptr<MediaRouteController> route_controller2 = | |
| 1319 router()->GetRouteController(kRouteId2); | |
| 1320 | |
| 1321 run_loop.RunUntilIdle(); | |
| 1322 } | |
| 1323 | |
| 1324 TEST_F(MediaRouterMojoImplTest, GetRouteControllerAfterInvalidation) { | |
| 1325 base::RunLoop run_loop; | |
| 1326 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), | |
| 1327 std::vector<std::string>()); | |
| 1328 | |
| 1329 EXPECT_CALL(mock_media_route_provider_, | |
| 1330 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1331 .Times(2) | |
| 1332 .WillRepeatedly(Invoke(OnCreateMediaRouteController)); | |
| 1333 | |
| 1334 scoped_refptr<MediaRouteController> route_controller = | |
| 1335 router()->GetRouteController(kRouteId); | |
| 1336 // Invalidate the MediaRouteController. | |
| 1337 route_controller = nullptr; | |
| 1338 // Call again with the same route ID. Since we've invalidated the | |
| 1339 // MediaRouteController, CreateMediaRouteController() should be called again. | |
| 1340 route_controller = router()->GetRouteController(kRouteId); | |
| 1341 | |
| 1342 run_loop.RunUntilIdle(); | |
| 1343 } | |
| 1344 | |
| 1345 TEST_F(MediaRouterMojoImplTest, GetRouteControllerAfterRouteInvalidation) { | |
| 1346 base::RunLoop run_loop; | |
| 1347 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, | |
| 1348 std::string(), std::vector<std::string>()); | |
| 1349 | |
| 1350 EXPECT_CALL(mock_media_route_provider_, | |
| 1351 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1352 .WillOnce(Invoke(OnCreateMediaRouteController)); | |
| 1353 EXPECT_CALL(mock_media_route_provider_, | |
| 1354 CreateMediaRouteControllerInternal(kRouteId2, _, _)) | |
| 1355 .Times(2) | |
| 1356 .WillRepeatedly(Invoke(OnCreateMediaRouteController)); | |
| 1357 | |
| 1358 MockMediaRouteControllerObserver observer1a( | |
| 1359 router()->GetRouteController(kRouteId)); | |
| 1360 MockMediaRouteControllerObserver observer2a( | |
| 1361 router()->GetRouteController(kRouteId2)); | |
| 1362 | |
| 1363 // Update the routes list with |kRouteId| but without |kRouteId2|. This should | |
| 1364 // remove the controller for |kRouteId2|, resulting in | |
| 1365 // CreateMediaRouteController() getting called again for |kRouteId2| below. | |
| 1366 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), | |
| 1367 std::vector<std::string>()); | |
| 1368 // Add back |kRouteId2| so that a controller can be created for it. | |
| 1369 router()->OnRoutesUpdated({CreateMediaRoute(), CreateMediaRoute2()}, | |
| 1370 std::string(), std::vector<std::string>()); | |
| 1371 | |
| 1372 MockMediaRouteControllerObserver observer1b( | |
| 1373 router()->GetRouteController(kRouteId)); | |
| 1374 MockMediaRouteControllerObserver observer2b( | |
| 1375 router()->GetRouteController(kRouteId2)); | |
| 1376 | |
| 1377 run_loop.RunUntilIdle(); | |
| 1378 } | |
| 1379 | |
| 1380 TEST_F(MediaRouterMojoImplTest, FailToCreateRouteController) { | |
| 1381 base::RunLoop run_loop; | |
| 1382 router()->OnRoutesUpdated({CreateMediaRoute()}, std::string(), | |
| 1383 std::vector<std::string>()); | |
| 1384 | |
| 1385 EXPECT_CALL(mock_media_route_provider_, | |
| 1386 CreateMediaRouteControllerInternal(kRouteId, _, _)) | |
| 1387 .WillOnce(Invoke( | |
| 1388 [](Unused, Unused, | |
| 1389 const mojom::MediaRouteProvider:: | |
| 1390 CreateMediaRouteControllerCallback& cb) { cb.Run(false); })); | |
| 1391 MockMediaRouteControllerObserver observer( | |
| 1392 router()->GetRouteController(kRouteId)); | |
| 1393 | |
| 1394 // When the MediaRouter is notified that the MediaRouteProvider failed to | |
| 1395 // create a controller, the browser-side controller should be invalidated. | |
| 1396 EXPECT_CALL(observer, OnControllerInvalidated()); | |
| 1397 | |
| 1398 run_loop.RunUntilIdle(); | |
| 1399 } | |
| 1400 | |
| 1226 class MediaRouterMojoExtensionTest : public ::testing::Test { | 1401 class MediaRouterMojoExtensionTest : public ::testing::Test { |
| 1227 public: | 1402 public: |
| 1228 MediaRouterMojoExtensionTest() : process_manager_(nullptr) {} | 1403 MediaRouterMojoExtensionTest() : process_manager_(nullptr) {} |
| 1229 | 1404 |
| 1230 ~MediaRouterMojoExtensionTest() override {} | 1405 ~MediaRouterMojoExtensionTest() override {} |
| 1231 | 1406 |
| 1232 protected: | 1407 protected: |
| 1233 void SetUp() override { | 1408 void SetUp() override { |
| 1234 // Set the extension's version number to be identical to the browser's. | 1409 // Set the extension's version number to be identical to the browser's. |
| 1235 extension_ = | 1410 extension_ = |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1596 EXPECT_CALL(mock_media_route_provider_, | 1771 EXPECT_CALL(mock_media_route_provider_, |
| 1597 UpdateMediaSinks(MediaSourceForDesktop().id())) | 1772 UpdateMediaSinks(MediaSourceForDesktop().id())) |
| 1598 .WillOnce(InvokeWithoutArgs([&run_loop2]() { | 1773 .WillOnce(InvokeWithoutArgs([&run_loop2]() { |
| 1599 run_loop2.Quit(); | 1774 run_loop2.Quit(); |
| 1600 })); | 1775 })); |
| 1601 | 1776 |
| 1602 run_loop2.Run(); | 1777 run_loop2.Run(); |
| 1603 } | 1778 } |
| 1604 | 1779 |
| 1605 } // namespace media_router | 1780 } // namespace media_router |
| OLD | NEW |