| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/media/cast_remoting_connector.h" | 5 #include "chrome/browser/media/cast_remoting_connector.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/memory/ptr_util.h" |
| 11 #include "base/memory/weak_ptr.h" | 12 #include "base/memory/weak_ptr.h" |
| 12 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
| 13 #include "chrome/browser/media/router/media_routes_observer.h" | |
| 14 #include "chrome/browser/media/router/mock_media_router.h" | 14 #include "chrome/browser/media/router/mock_media_router.h" |
| 15 #include "chrome/browser/media/router/route_message_observer.h" | |
| 16 #include "chrome/common/media_router/media_route.h" | 15 #include "chrome/common/media_router/media_route.h" |
| 17 #include "chrome/common/media_router/media_source.h" | 16 #include "chrome/common/media_router/media_source.h" |
| 18 #include "chrome/common/media_router/route_message.h" | |
| 19 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/test/test_browser_thread_bundle.h" | 18 #include "content/public/test/test_browser_thread_bundle.h" |
| 19 #include "media/mojo/interfaces/mirror_service_remoting.mojom.h" |
| 21 #include "media/mojo/interfaces/remoting.mojom.h" | 20 #include "media/mojo/interfaces/remoting.mojom.h" |
| 22 #include "mojo/public/cpp/bindings/binding.h" | 21 #include "mojo/public/cpp/bindings/binding.h" |
| 23 #include "testing/gmock/include/gmock/gmock.h" | 22 #include "testing/gmock/include/gmock/gmock.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 25 | 24 |
| 26 using content::BrowserThread; | 25 using content::BrowserThread; |
| 27 | 26 |
| 28 using media::mojom::RemoterPtr; | 27 using media::mojom::RemoterPtr; |
| 29 using media::mojom::RemoterRequest; | 28 using media::mojom::RemoterRequest; |
| 30 using media::mojom::RemotingSinkCapabilities; | 29 using media::mojom::RemotingSinkCapabilities; |
| 31 using media::mojom::RemotingSourcePtr; | 30 using media::mojom::RemotingSourcePtr; |
| 32 using media::mojom::RemotingSourceRequest; | 31 using media::mojom::RemotingSourceRequest; |
| 33 using media::mojom::RemotingStartFailReason; | 32 using media::mojom::RemotingStartFailReason; |
| 34 using media::mojom::RemotingStopReason; | 33 using media::mojom::RemotingStopReason; |
| 35 | 34 using media::mojom::MirrorServiceRemoterPtr; |
| 36 using media_router::MediaRoutesObserver; | 35 using media::mojom::MirrorServiceRemoterRequest; |
| 37 using media_router::MediaRoute; | 36 using media::mojom::MirrorServiceRemotingSourcePtr; |
| 38 using media_router::MediaSource; | 37 using media::mojom::MirrorServiceRemotingSourceRequest; |
| 39 using media_router::RouteMessage; | |
| 40 using media_router::RouteMessageObserver; | |
| 41 | 38 |
| 42 using ::testing::_; | 39 using ::testing::_; |
| 43 using ::testing::AtLeast; | 40 using ::testing::AtLeast; |
| 44 | 41 |
| 45 namespace { | 42 namespace { |
| 46 | 43 |
| 47 constexpr char kRemotingMediaSource[] = | 44 constexpr int32_t kRemotingTabId = 2; |
| 48 "urn:x-org.chromium.media:source:tab_content_remoting:123"; | |
| 49 constexpr char kRemotingMediaSink[] = "wiggles"; | |
| 50 constexpr char kRemotingMediaRoute[] = | |
| 51 "urn:x-org.chromium:media:route:garbly_gook_ssi7m4oa8oma7rasd/cast-wiggles"; | |
| 52 | |
| 53 constexpr char kTabMirroringMediaSource[] = | |
| 54 "urn:x-org.chromium.media:source:tab:123"; | |
| 55 constexpr char kTabMirroringMediaRoute[] = | |
| 56 "urn:x-org.chromium:media:route:bloopity_blop_ohun48i56nh9oid/cast-wiggles"; | |
| 57 | 45 |
| 58 constexpr RemotingSinkCapabilities kAllCapabilities = | 46 constexpr RemotingSinkCapabilities kAllCapabilities = |
| 59 RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING; | 47 RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING; |
| 60 | 48 |
| 61 // Implements basic functionality of a subset of the MediaRouter for use by the | 49 // Implements basic functionality of a subset of the MediaRouter for use by the |
| 62 // unit tests in this module. Note that MockMediaRouter will complain at runtime | 50 // unit tests in this module. Note that MockMediaRouter will complain at runtime |
| 63 // if any methods were called that should not have been called. | 51 // if any methods were called that should not have been called. |
| 64 class FakeMediaRouter : public media_router::MockMediaRouter { | 52 class FakeMediaRouter : public media_router::MockMediaRouter { |
| 65 public: | 53 public: |
| 66 FakeMediaRouter() | 54 FakeMediaRouter() : weak_factory_(this) {} |
| 67 : routes_observer_(nullptr), message_observer_(nullptr), | |
| 68 weak_factory_(this) {} | |
| 69 ~FakeMediaRouter() final {} | 55 ~FakeMediaRouter() final {} |
| 70 | 56 |
| 71 // | 57 void RegisterRemotingSource(int32_t tab_id, |
| 72 // These methods are called by test code to create/destroy a media route and | 58 CastRemotingConnector* remoting_source) final { |
| 73 // pass messages in both directions. | 59 EXPECT_EQ(-1, tab_id_); |
| 74 // | 60 tab_id_ = tab_id; |
| 75 | 61 connector_ = remoting_source; |
| 76 void OnRemotingRouteExists(bool exists) { | |
| 77 routes_.clear(); | |
| 78 | |
| 79 // Always add a non-remoting route to make sure CastRemotingConnector | |
| 80 // ignores non-remoting routes. | |
| 81 routes_.push_back(MediaRoute( | |
| 82 kTabMirroringMediaRoute, MediaSource(kTabMirroringMediaSource), | |
| 83 kRemotingMediaSink, "Cast Tab Mirroring", false, "", false)); | |
| 84 | |
| 85 if (exists) { | |
| 86 routes_.push_back(MediaRoute( | |
| 87 kRemotingMediaRoute, MediaSource(kRemotingMediaSource), | |
| 88 kRemotingMediaSink, "Cast Media Remoting", false, "", false)); | |
| 89 } else { | |
| 90 // Cancel delivery of all messages in both directions. | |
| 91 inbound_messages_.clear(); | |
| 92 for (auto& entry : outbound_messages_) { | |
| 93 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 94 base::BindOnce(std::move(entry.second), false)); | |
| 95 } | |
| 96 outbound_messages_.clear(); | |
| 97 } | |
| 98 | |
| 99 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 100 base::BindOnce(&FakeMediaRouter::DoUpdateRoutes, | |
| 101 weak_factory_.GetWeakPtr())); | |
| 102 } | 62 } |
| 103 | 63 |
| 104 void OnMessageFromProvider(const std::string& message) { | 64 void UnregisterRemotingSource(int32_t tab_id) final { |
| 105 inbound_messages_.push_back(RouteMessage()); | 65 EXPECT_EQ(tab_id, tab_id_); |
| 106 inbound_messages_.back().type = RouteMessage::TEXT; | 66 tab_id_ = -1; |
| 107 inbound_messages_.back().text = message; | 67 connector_ = nullptr; |
| 108 BrowserThread::PostTask( | |
| 109 BrowserThread::UI, FROM_HERE, | |
| 110 base::BindOnce(&FakeMediaRouter::DoDeliverInboundMessages, | |
| 111 weak_factory_.GetWeakPtr())); | |
| 112 } | 68 } |
| 113 | 69 |
| 114 void OnBinaryMessageFromProvider(const std::vector<uint8_t>& message) { | 70 void OnMediaRemoterCreated( |
| 115 inbound_messages_.push_back(RouteMessage()); | 71 int32_t tab_id, |
| 116 inbound_messages_.back().type = RouteMessage::BINARY; | 72 MirrorServiceRemoterPtr remoter, |
| 117 inbound_messages_.back().binary = std::vector<uint8_t>(message); | 73 MirrorServiceRemotingSourceRequest remoting_source) { |
| 118 BrowserThread::PostTask( | 74 if (tab_id != tab_id_) |
| 119 BrowserThread::UI, FROM_HERE, | 75 return; |
| 120 base::BindOnce(&FakeMediaRouter::DoDeliverInboundMessages, | 76 |
| 121 weak_factory_.GetWeakPtr())); | 77 EXPECT_TRUE(connector_); |
| 78 connector_->ConnectToService(std::move(remoting_source), |
| 79 std::move(remoter)); |
| 122 } | 80 } |
| 123 | 81 |
| 124 void TakeMessagesSentToProvider(RouteMessage::Type type, | 82 // Get the registered tab ID. |
| 125 std::vector<RouteMessage>* messages) { | 83 int32_t tab_id() const { return tab_id_; } |
| 126 decltype(outbound_messages_) untaken_messages; | |
| 127 for (auto& entry : outbound_messages_) { | |
| 128 if (entry.first.type == type) { | |
| 129 messages->push_back(entry.first); | |
| 130 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 131 base::BindOnce(std::move(entry.second), true)); | |
| 132 } else { | |
| 133 untaken_messages.push_back(std::move(entry)); | |
| 134 } | |
| 135 } | |
| 136 outbound_messages_.swap(untaken_messages); | |
| 137 } | |
| 138 | |
| 139 protected: | |
| 140 void RegisterMediaRoutesObserver(MediaRoutesObserver* observer) final { | |
| 141 CHECK(!routes_observer_); | |
| 142 routes_observer_ = observer; | |
| 143 CHECK(routes_observer_); | |
| 144 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 145 base::BindOnce(&FakeMediaRouter::DoUpdateRoutes, | |
| 146 weak_factory_.GetWeakPtr())); | |
| 147 } | |
| 148 | |
| 149 void UnregisterMediaRoutesObserver(MediaRoutesObserver* observer) final { | |
| 150 CHECK_EQ(routes_observer_, observer); | |
| 151 routes_observer_ = nullptr; | |
| 152 } | |
| 153 | |
| 154 void RegisterRouteMessageObserver(RouteMessageObserver* observer) final { | |
| 155 CHECK(!message_observer_); | |
| 156 message_observer_ = observer; | |
| 157 CHECK(message_observer_); | |
| 158 } | |
| 159 | |
| 160 void UnregisterRouteMessageObserver(RouteMessageObserver* observer) final { | |
| 161 CHECK_EQ(message_observer_, observer); | |
| 162 message_observer_ = nullptr; | |
| 163 } | |
| 164 | |
| 165 void SendRouteMessage(const MediaRoute::Id& route_id, | |
| 166 const std::string& text, | |
| 167 SendRouteMessageCallback callback) final { | |
| 168 EXPECT_EQ(message_observer_->route_id(), route_id); | |
| 169 ASSERT_FALSE(callback.is_null()); | |
| 170 RouteMessage message; | |
| 171 message.type = RouteMessage::TEXT; | |
| 172 message.text = text; | |
| 173 outbound_messages_.push_back(std::make_pair(message, std::move(callback))); | |
| 174 } | |
| 175 | |
| 176 void SendRouteBinaryMessage(const MediaRoute::Id& route_id, | |
| 177 std::unique_ptr<std::vector<uint8_t>> data, | |
| 178 SendRouteMessageCallback callback) final { | |
| 179 EXPECT_EQ(message_observer_->route_id(), route_id); | |
| 180 ASSERT_TRUE(!!data); | |
| 181 ASSERT_FALSE(callback.is_null()); | |
| 182 RouteMessage message; | |
| 183 message.type = RouteMessage::BINARY; | |
| 184 message.binary = std::move(*data); | |
| 185 outbound_messages_.push_back(std::make_pair(message, std::move(callback))); | |
| 186 } | |
| 187 | 84 |
| 188 private: | 85 private: |
| 189 // Asynchronous callback to notify the MediaRoutesObserver of a change in | 86 int32_t tab_id_ = -1; |
| 190 // routes. | 87 CastRemotingConnector* connector_ = nullptr; |
| 191 void DoUpdateRoutes() { | |
| 192 if (routes_observer_) | |
| 193 routes_observer_->OnRoutesUpdated(routes_, std::vector<MediaRoute::Id>()); | |
| 194 } | |
| 195 | |
| 196 // Asynchronous callback to deliver messages to the RouteMessageObserver. | |
| 197 void DoDeliverInboundMessages() { | |
| 198 if (message_observer_) | |
| 199 message_observer_->OnMessagesReceived(inbound_messages_); | |
| 200 inbound_messages_.clear(); | |
| 201 } | |
| 202 | |
| 203 MediaRoutesObserver* routes_observer_; | |
| 204 RouteMessageObserver* message_observer_; | |
| 205 | |
| 206 std::vector<MediaRoute> routes_; | |
| 207 // Messages from Cast Provider to the connector. | |
| 208 std::vector<RouteMessage> inbound_messages_; | |
| 209 // Messages from the connector to the Cast Provider. | |
| 210 using OutboundMessageAndCallback = | |
| 211 std::pair<RouteMessage, SendRouteMessageCallback>; | |
| 212 std::vector<OutboundMessageAndCallback> outbound_messages_; | |
| 213 | 88 |
| 214 base::WeakPtrFactory<FakeMediaRouter> weak_factory_; | 89 base::WeakPtrFactory<FakeMediaRouter> weak_factory_; |
| 215 }; | 90 }; |
| 216 | 91 |
| 217 class MockRemotingSource : public media::mojom::RemotingSource { | 92 class MockRemotingSource : public media::mojom::RemotingSource { |
| 218 public: | 93 public: |
| 219 MockRemotingSource() : binding_(this) {} | 94 MockRemotingSource() : binding_(this) {} |
| 220 ~MockRemotingSource() final {} | 95 ~MockRemotingSource() final {} |
| 221 | 96 |
| 222 void Bind(RemotingSourceRequest request) { | 97 void Bind(RemotingSourceRequest request) { |
| 223 binding_.Bind(std::move(request)); | 98 binding_.Bind(std::move(request)); |
| 224 } | 99 } |
| 225 | 100 |
| 226 MOCK_METHOD1(OnSinkAvailable, void(RemotingSinkCapabilities)); | 101 MOCK_METHOD1(OnSinkAvailable, void(RemotingSinkCapabilities)); |
| 227 MOCK_METHOD0(OnSinkGone, void()); | 102 MOCK_METHOD0(OnSinkGone, void()); |
| 228 MOCK_METHOD0(OnStarted, void()); | 103 MOCK_METHOD0(OnStarted, void()); |
| 229 MOCK_METHOD1(OnStartFailed, void(RemotingStartFailReason)); | 104 MOCK_METHOD1(OnStartFailed, void(RemotingStartFailReason)); |
| 230 MOCK_METHOD1(OnMessageFromSink, void(const std::vector<uint8_t>&)); | 105 MOCK_METHOD1(OnMessageFromSink, void(const std::vector<uint8_t>&)); |
| 231 MOCK_METHOD1(OnStopped, void(RemotingStopReason)); | 106 MOCK_METHOD1(OnStopped, void(RemotingStopReason)); |
| 232 | 107 |
| 233 private: | 108 private: |
| 234 mojo::Binding<media::mojom::RemotingSource> binding_; | 109 mojo::Binding<media::mojom::RemotingSource> binding_; |
| 235 }; | 110 }; |
| 236 | 111 |
| 112 class MockMediaRemoter : public media::mojom::MirrorServiceRemoter { |
| 113 public: |
| 114 explicit MockMediaRemoter(FakeMediaRouter* media_router) : binding_(this) { |
| 115 MirrorServiceRemoterPtr remoter; |
| 116 binding_.Bind(mojo::MakeRequest(&remoter)); |
| 117 media_router->OnMediaRemoterCreated(kRemotingTabId, std::move(remoter), |
| 118 mojo::MakeRequest(&source_)); |
| 119 } |
| 120 ~MockMediaRemoter() final {} |
| 121 |
| 122 void OnSinkAvailable() { |
| 123 media::mojom::SinkCapabilitiesPtr capabilities = |
| 124 media::mojom::SinkCapabilities::New(); |
| 125 source_->OnSinkAvailable(std::move(capabilities)); |
| 126 } |
| 127 |
| 128 void SendMessageToSource(const std::vector<uint8_t>& message) { |
| 129 source_->OnMessageFromSink(message); |
| 130 } |
| 131 |
| 132 void OnStopped(RemotingStopReason reason) { source_->OnStopped(reason); } |
| 133 |
| 134 void OnError() { source_->OnError(); } |
| 135 |
| 136 // media::mojom::MirrorServiceRemoter implementations. |
| 137 void StartDataStreams(bool audio, |
| 138 bool video, |
| 139 StartDataStreamsCallback callback) override {} |
| 140 MOCK_METHOD0(Start, void()); |
| 141 MOCK_METHOD1(Stop, void(RemotingStopReason)); |
| 142 MOCK_METHOD1(SendMessageToSink, void(const std::vector<uint8_t>&)); |
| 143 |
| 144 private: |
| 145 mojo::Binding<media::mojom::MirrorServiceRemoter> binding_; |
| 146 MirrorServiceRemotingSourcePtr source_; |
| 147 }; |
| 148 |
| 237 } // namespace | 149 } // namespace |
| 238 | 150 |
| 239 class CastRemotingConnectorTest : public ::testing::Test { | 151 class CastRemotingConnectorTest : public ::testing::Test { |
| 240 public: | 152 public: |
| 241 CastRemotingConnectorTest() | 153 CastRemotingConnectorTest() : connector_(&media_router_, kRemotingTabId) { |
| 242 : connector_(&media_router_, kRemotingMediaSource) { | |
| 243 // HACK: Override feature flags for testing. | 154 // HACK: Override feature flags for testing. |
| 244 const_cast<RemotingSinkCapabilities&>(connector_.enabled_features_) = | 155 const_cast<RemotingSinkCapabilities&>(connector_.enabled_features_) = |
| 245 kAllCapabilities; | 156 kAllCapabilities; |
| 157 |
| 158 EXPECT_EQ(kRemotingTabId, media_router_.tab_id()); |
| 246 } | 159 } |
| 247 | 160 |
| 248 void TearDown() final { | 161 void TearDown() final { |
| 249 // Allow any pending Mojo operations to complete before destruction. For | 162 // Allow any pending Mojo operations to complete before destruction. For |
| 250 // example, when one end of a Mojo message pipe is closed, a task is posted | 163 // example, when one end of a Mojo message pipe is closed, a task is posted |
| 251 // to later destroy objects that were owned by the message pipe. | 164 // to later destroy objects that were owned by the message pipe. |
| 252 RunUntilIdle(); | 165 RunUntilIdle(); |
| 253 } | 166 } |
| 254 | 167 |
| 255 protected: | 168 protected: |
| 256 RemoterPtr CreateRemoter(MockRemotingSource* source) { | 169 RemoterPtr CreateRemoter(MockRemotingSource* source) { |
| 257 RemotingSourcePtr source_ptr; | 170 RemotingSourcePtr source_ptr; |
| 258 source->Bind(mojo::MakeRequest(&source_ptr)); | 171 source->Bind(mojo::MakeRequest(&source_ptr)); |
| 259 RemoterPtr remoter_ptr; | 172 RemoterPtr remoter_ptr; |
| 260 connector_.CreateBridge(std::move(source_ptr), | 173 connector_.CreateBridge(std::move(source_ptr), |
| 261 mojo::MakeRequest(&remoter_ptr)); | 174 mojo::MakeRequest(&remoter_ptr)); |
| 262 return remoter_ptr; | 175 return remoter_ptr; |
| 263 } | 176 } |
| 264 | 177 |
| 265 void ProviderDiscoversSink() { | |
| 266 media_router_.OnRemotingRouteExists(true); | |
| 267 } | |
| 268 | |
| 269 void ProviderLosesSink() { | |
| 270 media_router_.OnRemotingRouteExists(false); | |
| 271 } | |
| 272 | |
| 273 void ConnectorSentMessageToProvider(const std::string& expected_message) { | |
| 274 std::vector<RouteMessage> messages; | |
| 275 media_router_.TakeMessagesSentToProvider(RouteMessage::TEXT, &messages); | |
| 276 bool did_see_expected_message = false; | |
| 277 for (const RouteMessage& message : messages) { | |
| 278 if (message.text && expected_message == *message.text) { | |
| 279 did_see_expected_message = true; | |
| 280 } else { | |
| 281 ADD_FAILURE() | |
| 282 << "Unexpected message: " << message.ToHumanReadableString(); | |
| 283 } | |
| 284 } | |
| 285 EXPECT_TRUE(did_see_expected_message); | |
| 286 } | |
| 287 | |
| 288 void ConnectorSentMessageToSink( | |
| 289 const std::vector<uint8_t>& expected_message) { | |
| 290 std::vector<RouteMessage> messages; | |
| 291 media_router_.TakeMessagesSentToProvider(RouteMessage::BINARY, &messages); | |
| 292 bool did_see_expected_message = false; | |
| 293 for (const RouteMessage& message : messages) { | |
| 294 if (message.binary && expected_message == *message.binary) { | |
| 295 did_see_expected_message = true; | |
| 296 } else { | |
| 297 ADD_FAILURE() | |
| 298 << "Unexpected message: " << message.ToHumanReadableString(); | |
| 299 } | |
| 300 } | |
| 301 EXPECT_TRUE(did_see_expected_message); | |
| 302 } | |
| 303 | |
| 304 void ConnectorSentNoMessagesToProvider() { | |
| 305 std::vector<RouteMessage> messages; | |
| 306 media_router_.TakeMessagesSentToProvider(RouteMessage::TEXT, &messages); | |
| 307 EXPECT_TRUE(messages.empty()); | |
| 308 } | |
| 309 | |
| 310 void ConnectorSentNoMessagesToSink() { | |
| 311 std::vector<RouteMessage> messages; | |
| 312 media_router_.TakeMessagesSentToProvider(RouteMessage::BINARY, &messages); | |
| 313 EXPECT_TRUE(messages.empty()); | |
| 314 } | |
| 315 | |
| 316 void ProviderPassesMessageFromSink( | |
| 317 const std::vector<uint8_t>& message) { | |
| 318 media_router_.OnBinaryMessageFromProvider(message); | |
| 319 } | |
| 320 | |
| 321 void ProviderSaysToRemotingConnector(const std::string& message) { | |
| 322 media_router_.OnMessageFromProvider(message); | |
| 323 } | |
| 324 | |
| 325 void MediaRouterTerminatesRoute() { | |
| 326 media_router_.OnRemotingRouteExists(false); | |
| 327 } | |
| 328 | |
| 329 static void RunUntilIdle() { | 178 static void RunUntilIdle() { |
| 330 base::RunLoop().RunUntilIdle(); | 179 base::RunLoop().RunUntilIdle(); |
| 331 } | 180 } |
| 332 | 181 |
| 182 FakeMediaRouter media_router_; |
| 183 |
| 333 private: | 184 private: |
| 334 content::TestBrowserThreadBundle browser_thread_bundle_; | 185 content::TestBrowserThreadBundle browser_thread_bundle_; |
| 335 FakeMediaRouter media_router_; | |
| 336 CastRemotingConnector connector_; | 186 CastRemotingConnector connector_; |
| 337 }; | 187 }; |
| 338 | 188 |
| 339 TEST_F(CastRemotingConnectorTest, NeverNotifiesThatSinkIsAvailable) { | 189 TEST_F(CastRemotingConnectorTest, NeverNotifiesThatSinkIsAvailable) { |
| 340 MockRemotingSource source; | 190 MockRemotingSource source; |
| 341 RemoterPtr remoter = CreateRemoter(&source); | 191 RemoterPtr remoter = CreateRemoter(&source); |
| 342 | 192 |
| 343 EXPECT_CALL(source, OnSinkAvailable(_)).Times(0); | 193 EXPECT_CALL(source, OnSinkAvailable(_)).Times(0); |
| 344 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(0)); | 194 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(0)); |
| 345 RunUntilIdle(); | 195 RunUntilIdle(); |
| 346 } | 196 } |
| 347 | 197 |
| 348 TEST_F(CastRemotingConnectorTest, NotifiesWhenSinkIsAvailableAndThenGone) { | 198 TEST_F(CastRemotingConnectorTest, NotifiesWhenSinkIsAvailableAndThenGone) { |
| 349 MockRemotingSource source; | 199 MockRemotingSource source; |
| 350 RemoterPtr remoter = CreateRemoter(&source); | 200 RemoterPtr remoter = CreateRemoter(&source); |
| 351 | 201 |
| 202 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 203 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 204 |
| 352 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); | 205 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); |
| 353 ProviderDiscoversSink(); | 206 media_remoter->OnSinkAvailable(); |
| 354 RunUntilIdle(); | 207 RunUntilIdle(); |
| 355 | 208 |
| 356 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(1)); | 209 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(1)); |
| 357 ProviderLosesSink(); | 210 media_remoter.reset(); |
| 358 RunUntilIdle(); | 211 RunUntilIdle(); |
| 359 } | 212 } |
| 360 | 213 |
| 361 TEST_F(CastRemotingConnectorTest, | 214 TEST_F(CastRemotingConnectorTest, |
| 362 NotifiesMultipleSourcesWhenSinkIsAvailableAndThenGone) { | 215 NotifiesMultipleSourcesWhenSinkIsAvailableAndThenGone) { |
| 363 MockRemotingSource source1; | 216 MockRemotingSource source1; |
| 364 RemoterPtr remoter1 = CreateRemoter(&source1); | 217 RemoterPtr remoter1 = CreateRemoter(&source1); |
| 365 MockRemotingSource source2; | 218 MockRemotingSource source2; |
| 366 RemoterPtr remoter2 = CreateRemoter(&source2); | 219 RemoterPtr remoter2 = CreateRemoter(&source2); |
| 367 | 220 |
| 221 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 222 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 223 |
| 368 EXPECT_CALL(source1, OnSinkAvailable(kAllCapabilities)).Times(1); | 224 EXPECT_CALL(source1, OnSinkAvailable(kAllCapabilities)).Times(1); |
| 369 EXPECT_CALL(source2, OnSinkAvailable(kAllCapabilities)).Times(1); | 225 EXPECT_CALL(source2, OnSinkAvailable(kAllCapabilities)).Times(1); |
| 370 ProviderDiscoversSink(); | 226 media_remoter->OnSinkAvailable(); |
| 371 RunUntilIdle(); | 227 RunUntilIdle(); |
| 372 | 228 |
| 373 EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1)); | 229 EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1)); |
| 374 EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1)); | 230 EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1)); |
| 375 ProviderLosesSink(); | 231 media_remoter.reset(); |
| 376 RunUntilIdle(); | 232 RunUntilIdle(); |
| 377 } | 233 } |
| 378 | 234 |
| 379 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemotingSourceFirst) { | 235 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemotingSourceFirst) { |
| 380 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource); | 236 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource); |
| 381 RemoterPtr remoter = CreateRemoter(source.get()); | 237 RemoterPtr remoter = CreateRemoter(source.get()); |
| 382 | 238 |
| 239 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 240 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 241 |
| 383 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1); | 242 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1); |
| 384 ProviderDiscoversSink(); | 243 media_remoter->OnSinkAvailable(); |
| 385 RunUntilIdle(); | 244 RunUntilIdle(); |
| 386 | 245 |
| 387 source.reset(); | 246 source.reset(); |
| 388 RunUntilIdle(); | 247 RunUntilIdle(); |
| 389 } | 248 } |
| 390 | 249 |
| 391 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemoterFirst) { | 250 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemoterFirst) { |
| 392 MockRemotingSource source; | 251 MockRemotingSource source; |
| 393 RemoterPtr remoter = CreateRemoter(&source); | 252 RemoterPtr remoter = CreateRemoter(&source); |
| 394 | 253 |
| 254 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 255 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 256 |
| 395 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); | 257 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); |
| 396 ProviderDiscoversSink(); | 258 media_remoter->OnSinkAvailable(); |
| 397 RunUntilIdle(); | 259 RunUntilIdle(); |
| 398 | 260 |
| 399 remoter.reset(); | 261 remoter.reset(); |
| 400 RunUntilIdle(); | 262 RunUntilIdle(); |
| 401 } | 263 } |
| 402 | 264 |
| 265 TEST_F(CastRemotingConnectorTest, NoConnectedMediaRemoter) { |
| 266 MockRemotingSource source; |
| 267 RemoterPtr remoter = CreateRemoter(&source); |
| 268 |
| 269 EXPECT_CALL(source, |
| 270 OnStartFailed(RemotingStartFailReason::SERVICE_NOT_CONNECTED)) |
| 271 .Times(1); |
| 272 remoter->Start(); |
| 273 RunUntilIdle(); |
| 274 } |
| 275 |
| 403 namespace { | 276 namespace { |
| 404 | 277 |
| 405 // The possible ways a remoting session may be terminated in the "full | 278 // The possible ways a remoting session may be terminated in the "full |
| 406 // run-through" tests. | 279 // run-through" tests. |
| 407 enum HowItEnds { | 280 enum HowItEnds { |
| 408 SOURCE_TERMINATES, // The render process decides to end remoting. | 281 SOURCE_TERMINATES, // The render process decides to end remoting. |
| 409 MOJO_PIPE_CLOSES, // A Mojo message pipe closes unexpectedly. | 282 MOJO_PIPE_CLOSES, // A Mojo message pipe closes unexpectedly. |
| 410 ROUTE_TERMINATES, // The Media Router UI was used to terminate the route. | 283 ROUTE_TERMINATES, // The Media Router UI was used to terminate the route. |
| 411 EXTERNAL_FAILURE, // The sink is cut-off, perhaps due to a network outage. | 284 EXTERNAL_FAILURE, // The sink is cut-off, perhaps due to a network outage. |
| 412 }; | 285 }; |
| 413 | 286 |
| 414 } // namespace | 287 } // namespace |
| 415 | 288 |
| 416 class CastRemotingConnectorFullSessionTest | 289 class CastRemotingConnectorFullSessionTest |
| 417 : public CastRemotingConnectorTest, | 290 : public CastRemotingConnectorTest, |
| 418 public ::testing::WithParamInterface<HowItEnds> { | 291 public ::testing::WithParamInterface<HowItEnds> { |
| 419 public: | 292 public: |
| 420 HowItEnds how_it_ends() const { return GetParam(); } | 293 HowItEnds how_it_ends() const { return GetParam(); } |
| 421 }; | 294 }; |
| 422 | 295 |
| 423 // Performs a full run-through of starting and stopping remoting, with | 296 // Performs a full run-through of starting and stopping remoting, with |
| 424 // communications between source and sink established at the correct times, and | 297 // communications between source and sink established at the correct times, and |
| 425 // tests that end-to-end behavior is correct depending on what caused the | 298 // tests that end-to-end behavior is correct depending on what caused the |
| 426 // remoting session to end. | 299 // remoting session to end. |
| 427 TEST_P(CastRemotingConnectorFullSessionTest, GoesThroughAllTheMotions) { | 300 TEST_P(CastRemotingConnectorFullSessionTest, GoesThroughAllTheMotions) { |
| 428 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource()); | 301 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource()); |
| 429 RemoterPtr remoter = CreateRemoter(source.get()); | 302 RemoterPtr remoter = CreateRemoter(source.get()); |
| 430 std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource()); | 303 std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource()); |
| 431 RemoterPtr other_remoter = CreateRemoter(other_source.get()); | 304 RemoterPtr other_remoter = CreateRemoter(other_source.get()); |
| 305 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 306 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 432 | 307 |
| 433 // Throughout this test |other_source| should not participate in the | 308 // Throughout this test |other_source| should not participate in the |
| 434 // remoting session, and so these method calls should never occur: | 309 // remoting session, and so these method calls should never occur: |
| 435 EXPECT_CALL(*other_source, OnStarted()).Times(0); | 310 EXPECT_CALL(*other_source, OnStarted()).Times(0); |
| 436 EXPECT_CALL(*other_source, OnStopped(_)).Times(0); | 311 EXPECT_CALL(*other_source, OnStopped(_)).Times(0); |
| 437 EXPECT_CALL(*other_source, OnMessageFromSink(_)).Times(0); | 312 EXPECT_CALL(*other_source, OnMessageFromSink(_)).Times(0); |
| 438 | 313 |
| 439 // Both sinks should be notified when the Cast Provider tells the connector | 314 // Both sinks should be notified when the Cast Provider tells the connector |
| 440 // a remoting sink is available. | 315 // a remoting sink is available. |
| 441 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) | 316 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) |
| 442 .RetiresOnSaturation(); | 317 .RetiresOnSaturation(); |
| 443 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) | 318 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) |
| 444 .RetiresOnSaturation(); | 319 .RetiresOnSaturation(); |
| 445 ProviderDiscoversSink(); | 320 media_remoter->OnSinkAvailable(); |
| 446 RunUntilIdle(); | 321 RunUntilIdle(); |
| 447 | 322 |
| 448 // When |source| starts a remoting session, |other_source| is notified the | 323 // When |source| starts a remoting session, |other_source| is notified the |
| 449 // sink is gone, the Cast Provider is notified that remoting has started, | 324 // sink is gone, the Cast Provider is notified that remoting has started, |
| 450 // and |source| is notified that its request was successful. | 325 // and |source| is notified that its request was successful. |
| 451 EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation(); | 326 EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation(); |
| 452 EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation(); | 327 EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation(); |
| 328 EXPECT_CALL(*media_remoter, Start()).Times(1).RetiresOnSaturation(); |
| 453 remoter->Start(); | 329 remoter->Start(); |
| 454 RunUntilIdle(); | 330 RunUntilIdle(); |
| 455 ConnectorSentMessageToProvider("START_CAST_REMOTING:session=1"); | |
| 456 | 331 |
| 457 // The |source| should now be able to send binary messages to the sink. | 332 // The |source| should now be able to send binary messages to the sink. |
| 458 // |other_source| should not! | 333 // |other_source| should not! |
| 459 const std::vector<uint8_t> message_to_sink = { 3, 1, 4, 1, 5, 9 }; | 334 const std::vector<uint8_t> message_to_sink = { 3, 1, 4, 1, 5, 9 }; |
| 335 EXPECT_CALL(*media_remoter, SendMessageToSink(message_to_sink)) |
| 336 .Times(1) |
| 337 .RetiresOnSaturation(); |
| 460 remoter->SendMessageToSink(message_to_sink); | 338 remoter->SendMessageToSink(message_to_sink); |
| 461 const std::vector<uint8_t> ignored_message_to_sink = { 1, 2, 3 }; | 339 const std::vector<uint8_t> ignored_message_to_sink = { 1, 2, 3 }; |
| 340 EXPECT_CALL(*media_remoter, SendMessageToSink(ignored_message_to_sink)) |
| 341 .Times(0); |
| 462 other_remoter->SendMessageToSink(ignored_message_to_sink); | 342 other_remoter->SendMessageToSink(ignored_message_to_sink); |
| 463 RunUntilIdle(); | 343 RunUntilIdle(); |
| 464 ConnectorSentMessageToSink(message_to_sink); | |
| 465 | 344 |
| 466 // The sink should also be able to send binary messages to the |source|. | 345 // The sink should also be able to send binary messages to the |source|. |
| 467 const std::vector<uint8_t> message_to_source = { 2, 7, 1, 8, 2, 8 }; | 346 const std::vector<uint8_t> message_to_source = { 2, 7, 1, 8, 2, 8 }; |
| 468 EXPECT_CALL(*source, OnMessageFromSink(message_to_source)).Times(1) | 347 EXPECT_CALL(*source, OnMessageFromSink(message_to_source)).Times(1) |
| 469 .RetiresOnSaturation(); | 348 .RetiresOnSaturation(); |
| 470 ProviderPassesMessageFromSink(message_to_source); | 349 media_remoter->SendMessageToSource(message_to_source); |
| 471 RunUntilIdle(); | 350 RunUntilIdle(); |
| 472 | 351 |
| 473 // The |other_source| should not be allowed to start a remoting session. | 352 // The |other_source| should not be allowed to start a remoting session. |
| 474 EXPECT_CALL(*other_source, | 353 EXPECT_CALL(*other_source, |
| 475 OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE)) | 354 OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE)) |
| 476 .Times(1).RetiresOnSaturation(); | 355 .Times(1).RetiresOnSaturation(); |
| 477 other_remoter->Start(); | 356 other_remoter->Start(); |
| 478 RunUntilIdle(); | 357 RunUntilIdle(); |
| 479 ConnectorSentNoMessagesToProvider(); | |
| 480 | 358 |
| 481 // What happens from here depends on how this remoting session will end... | 359 // What happens from here depends on how this remoting session will end... |
| 482 switch (how_it_ends()) { | 360 switch (how_it_ends()) { |
| 483 case SOURCE_TERMINATES: { | 361 case SOURCE_TERMINATES: { |
| 484 // When the |source| stops the remoting session, the Cast Provider is | 362 // When the |source| stops the remoting session, the Cast Provider is |
| 485 // notified the session has stopped, and the |source| receives both an | 363 // notified the session has stopped, and the |source| receives both an |
| 486 // OnStopped() and an OnSinkGone() notification. | 364 // OnStopped() and an OnSinkGone() notification. |
| 487 const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK; | 365 const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK; |
| 488 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); | 366 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); |
| 489 EXPECT_CALL(*source, OnStopped(reason)).Times(1).RetiresOnSaturation(); | 367 EXPECT_CALL(*source, OnStopped(reason)).Times(1).RetiresOnSaturation(); |
| 368 EXPECT_CALL(*media_remoter, Stop(reason)).Times(1).RetiresOnSaturation(); |
| 490 remoter->Stop(reason); | 369 remoter->Stop(reason); |
| 491 RunUntilIdle(); | 370 RunUntilIdle(); |
| 492 ConnectorSentMessageToProvider("STOP_CAST_REMOTING:session=1"); | |
| 493 | 371 |
| 494 // Since remoting is stopped, any further messaging in either direction | 372 // Since remoting is stopped, any further messaging in either direction |
| 495 // must be dropped. | 373 // must be dropped. |
| 496 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; | 374 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; |
| 497 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; | 375 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; |
| 498 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); | 376 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); |
| 377 EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); |
| 499 remoter->SendMessageToSink(message_to_sink); | 378 remoter->SendMessageToSink(message_to_sink); |
| 500 ProviderPassesMessageFromSink(message_to_source); | 379 media_remoter->SendMessageToSource(message_to_source); |
| 501 RunUntilIdle(); | 380 RunUntilIdle(); |
| 502 ConnectorSentNoMessagesToSink(); | |
| 503 | 381 |
| 504 // When the sink is ready, the Cast Provider sends a notification to the | 382 // When the sink is ready, the Cast Provider sends a notification to the |
| 505 // connector. The connector will notify both sources that a sink is once | 383 // connector. The connector will notify both sources that a sink is once |
| 506 // again available. | 384 // again available. |
| 507 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) | 385 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) |
| 508 .RetiresOnSaturation(); | 386 .RetiresOnSaturation(); |
| 509 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) | 387 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) |
| 510 .RetiresOnSaturation(); | 388 .RetiresOnSaturation(); |
| 511 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); | 389 media_remoter->OnSinkAvailable(); |
| 512 RunUntilIdle(); | 390 RunUntilIdle(); |
| 513 | 391 |
| 514 // When the sink is no longer available, the Cast Provider notifies the | 392 // When the sink is no longer available, the Cast Provider notifies the |
| 515 // connector, and both sources are then notified the sink is gone. | 393 // connector, and both sources are then notified the sink is gone. |
| 516 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); | 394 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); |
| 517 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); | 395 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); |
| 518 ProviderLosesSink(); | 396 media_remoter.reset(); |
| 519 RunUntilIdle(); | 397 RunUntilIdle(); |
| 520 | 398 |
| 521 break; | 399 break; |
| 522 } | 400 } |
| 523 | 401 |
| 524 case MOJO_PIPE_CLOSES: | 402 case MOJO_PIPE_CLOSES: |
| 525 // When the Mojo pipes for |other_source| close, this should not affect | 403 // When the Mojo pipes for |other_source| close, this should not affect |
| 526 // the current remoting session. | 404 // the current remoting session. |
| 405 EXPECT_CALL(*media_remoter, Stop(_)).Times(0); |
| 527 other_source.reset(); | 406 other_source.reset(); |
| 528 other_remoter.reset(); | 407 other_remoter.reset(); |
| 529 RunUntilIdle(); | 408 RunUntilIdle(); |
| 530 ConnectorSentNoMessagesToProvider(); | |
| 531 | 409 |
| 532 // Now, when the Mojo pipes for |source| close, the Cast Provider will be | 410 // Now, when the Mojo pipes for |source| close, the Cast Provider will be |
| 533 // notified that the session has stopped. | 411 // notified that the session has stopped. |
| 412 EXPECT_CALL(*media_remoter, Stop(_)).Times(1).RetiresOnSaturation(); |
| 534 source.reset(); | 413 source.reset(); |
| 535 remoter.reset(); | 414 remoter.reset(); |
| 536 RunUntilIdle(); | 415 RunUntilIdle(); |
| 537 ConnectorSentMessageToProvider("STOP_CAST_REMOTING:session=1"); | |
| 538 | |
| 539 // The Cast Provider will detect when the sink is ready for the next | |
| 540 // remoting session, and then notify the connector. However, there are no | |
| 541 // sources to propagate this notification to. | |
| 542 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); | |
| 543 RunUntilIdle(); | |
| 544 | 416 |
| 545 break; | 417 break; |
| 546 | 418 |
| 547 case ROUTE_TERMINATES: | 419 case ROUTE_TERMINATES: |
| 548 // When the Media Router terminates the route (e.g., because a user | 420 // When the Media Router terminates the route (e.g., because a user |
| 549 // terminated the route from the UI), the source and sink are immediately | 421 // terminated the route from the UI), the source and sink are immediately |
| 550 // cut off from one another. | 422 // cut off from one another. |
| 551 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); | 423 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); |
| 552 EXPECT_CALL(*source, OnStopped(RemotingStopReason::ROUTE_TERMINATED)) | |
| 553 .Times(1).RetiresOnSaturation(); | |
| 554 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(0)); | 424 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(0)); |
| 555 MediaRouterTerminatesRoute(); | |
| 556 RunUntilIdle(); | |
| 557 ConnectorSentNoMessagesToProvider(); | |
| 558 | |
| 559 // Furthermore, the connector and Cast Provider are also cut off from one | 425 // Furthermore, the connector and Cast Provider are also cut off from one |
| 560 // another and should not be able to exchange messages anymore. Therefore, | 426 // another and should not be able to exchange messages anymore. Therefore, |
| 561 // the connector will never try to notify the sources that the sink is | 427 // the connector will never try to notify the sources that the sink is |
| 562 // available again. | 428 // available again. |
| 563 EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); | 429 EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); |
| 564 EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); | 430 EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); |
| 565 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); | 431 media_remoter.reset(); |
| 566 RunUntilIdle(); | 432 RunUntilIdle(); |
| 567 | 433 |
| 568 break; | 434 break; |
| 569 | 435 |
| 570 case EXTERNAL_FAILURE: { | 436 case EXTERNAL_FAILURE: { |
| 571 // When the Cast Provider is cut-off from the sink, it sends a fail | 437 // When the Cast Provider is cut-off from the sink, it sends a fail |
| 572 // notification to the connector. The connector, in turn, force-stops the | 438 // notification to the connector. The connector, in turn, force-stops the |
| 573 // remoting session and notifies the |source|. | 439 // remoting session and notifies the |source|. |
| 574 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); | 440 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); |
| 575 EXPECT_CALL(*source, OnStopped(RemotingStopReason::UNEXPECTED_FAILURE)) | 441 EXPECT_CALL(*source, OnStopped(RemotingStopReason::UNEXPECTED_FAILURE)) |
| 576 .Times(1).RetiresOnSaturation(); | 442 .Times(1).RetiresOnSaturation(); |
| 577 ProviderSaysToRemotingConnector("FAILED_CAST_REMOTING:session=1"); | 443 EXPECT_CALL(*media_remoter, Stop(RemotingStopReason::UNEXPECTED_FAILURE)) |
| 444 .Times(1) |
| 445 .RetiresOnSaturation(); |
| 446 media_remoter->OnError(); |
| 578 RunUntilIdle(); | 447 RunUntilIdle(); |
| 579 | 448 |
| 580 // Since remoting is stopped, any further messaging in either direction | 449 // Since remoting is stopped, any further messaging in either direction |
| 581 // must be dropped. | 450 // must be dropped. |
| 582 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; | 451 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; |
| 583 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; | 452 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; |
| 584 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); | 453 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); |
| 454 EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); |
| 585 remoter->SendMessageToSink(message_to_sink); | 455 remoter->SendMessageToSink(message_to_sink); |
| 586 ProviderPassesMessageFromSink(message_to_source); | 456 media_remoter->SendMessageToSource(message_to_source); |
| 587 RunUntilIdle(); | |
| 588 ConnectorSentNoMessagesToSink(); | |
| 589 | |
| 590 // Later, if whatever caused the external failure has resolved, the Cast | |
| 591 // Provider will notify the connector that the sink is available one | |
| 592 // again. | |
| 593 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) | |
| 594 .RetiresOnSaturation(); | |
| 595 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) | |
| 596 .RetiresOnSaturation(); | |
| 597 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); | |
| 598 RunUntilIdle(); | 457 RunUntilIdle(); |
| 599 | 458 |
| 600 // When the sink is no longer available, the Cast Provider notifies the | 459 // When the sink is no longer available, the Cast Provider notifies the |
| 601 // connector, and both sources are then notified the sink is gone. | 460 // connector, and both sources are then notified the sink is gone. |
| 602 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); | 461 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); |
| 603 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); | 462 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); |
| 604 ProviderLosesSink(); | 463 media_remoter.reset(); |
| 605 RunUntilIdle(); | 464 RunUntilIdle(); |
| 606 | 465 |
| 607 break; | 466 break; |
| 608 } | 467 } |
| 609 } | 468 } |
| 610 } | 469 } |
| 611 | 470 |
| 612 INSTANTIATE_TEST_CASE_P(, CastRemotingConnectorFullSessionTest, | 471 INSTANTIATE_TEST_CASE_P(, CastRemotingConnectorFullSessionTest, |
| 613 ::testing::Values(SOURCE_TERMINATES, | 472 ::testing::Values(SOURCE_TERMINATES, |
| 614 MOJO_PIPE_CLOSES, | 473 MOJO_PIPE_CLOSES, |
| 615 ROUTE_TERMINATES, | 474 ROUTE_TERMINATES, |
| 616 EXTERNAL_FAILURE)); | 475 EXTERNAL_FAILURE)); |
| OLD | NEW |