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 DCHECK_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, |
105 inbound_messages_.push_back(RouteMessage()); | 65 CastRemotingConnector* remoting_source) final { |
106 inbound_messages_.back().type = RouteMessage::TEXT; | 66 DCHECK_EQ(tab_id, tab_id_); |
107 inbound_messages_.back().text = message; | 67 DCHECK_EQ(remoting_source, connector_); |
108 BrowserThread::PostTask( | 68 tab_id_ = -1; |
109 BrowserThread::UI, FROM_HERE, | 69 connector_ = nullptr; |
110 base::BindOnce(&FakeMediaRouter::DoDeliverInboundMessages, | |
111 weak_factory_.GetWeakPtr())); | |
112 } | 70 } |
113 | 71 |
114 void OnBinaryMessageFromProvider(const std::vector<uint8_t>& message) { | 72 void OnMediaRemoterCreated( |
115 inbound_messages_.push_back(RouteMessage()); | 73 int32_t tab_id, |
116 inbound_messages_.back().type = RouteMessage::BINARY; | 74 MirrorServiceRemoterPtr remoter, |
117 inbound_messages_.back().binary = std::vector<uint8_t>(message); | 75 MirrorServiceRemotingSourceRequest remoting_source) { |
118 BrowserThread::PostTask( | 76 if (tab_id != tab_id_) |
119 BrowserThread::UI, FROM_HERE, | 77 return; |
120 base::BindOnce(&FakeMediaRouter::DoDeliverInboundMessages, | 78 |
121 weak_factory_.GetWeakPtr())); | 79 DCHECK(connector_); |
| 80 connector_->ConnectToService(std::move(remoting_source), |
| 81 std::move(remoter)); |
122 } | 82 } |
123 | 83 |
124 void TakeMessagesSentToProvider(RouteMessage::Type type, | 84 // Get the registered tab ID. |
125 std::vector<RouteMessage>* messages) { | 85 int32_t tab_id() { 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 | 86 |
188 private: | 87 private: |
189 // Asynchronous callback to notify the MediaRoutesObserver of a change in | 88 int32_t tab_id_ = -1; |
190 // routes. | 89 CastRemotingConnector* connector_; |
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 | 90 |
214 base::WeakPtrFactory<FakeMediaRouter> weak_factory_; | 91 base::WeakPtrFactory<FakeMediaRouter> weak_factory_; |
215 }; | 92 }; |
216 | 93 |
217 class MockRemotingSource : public media::mojom::RemotingSource { | 94 class MockRemotingSource : public media::mojom::RemotingSource { |
218 public: | 95 public: |
219 MockRemotingSource() : binding_(this) {} | 96 MockRemotingSource() : binding_(this) {} |
220 ~MockRemotingSource() final {} | 97 ~MockRemotingSource() final {} |
221 | 98 |
222 void Bind(RemotingSourceRequest request) { | 99 void Bind(RemotingSourceRequest request) { |
223 binding_.Bind(std::move(request)); | 100 binding_.Bind(std::move(request)); |
224 } | 101 } |
225 | 102 |
226 MOCK_METHOD1(OnSinkAvailable, void(RemotingSinkCapabilities)); | 103 MOCK_METHOD1(OnSinkAvailable, void(RemotingSinkCapabilities)); |
227 MOCK_METHOD0(OnSinkGone, void()); | 104 MOCK_METHOD0(OnSinkGone, void()); |
228 MOCK_METHOD0(OnStarted, void()); | 105 MOCK_METHOD0(OnStarted, void()); |
229 MOCK_METHOD1(OnStartFailed, void(RemotingStartFailReason)); | 106 MOCK_METHOD1(OnStartFailed, void(RemotingStartFailReason)); |
230 MOCK_METHOD1(OnMessageFromSink, void(const std::vector<uint8_t>&)); | 107 MOCK_METHOD1(OnMessageFromSink, void(const std::vector<uint8_t>&)); |
231 MOCK_METHOD1(OnStopped, void(RemotingStopReason)); | 108 MOCK_METHOD1(OnStopped, void(RemotingStopReason)); |
232 | 109 |
233 private: | 110 private: |
234 mojo::Binding<media::mojom::RemotingSource> binding_; | 111 mojo::Binding<media::mojom::RemotingSource> binding_; |
235 }; | 112 }; |
236 | 113 |
| 114 class MockMediaRemoter : public media::mojom::MirrorServiceRemoter { |
| 115 public: |
| 116 explicit MockMediaRemoter(FakeMediaRouter* media_router) : binding_(this) { |
| 117 MirrorServiceRemoterPtr remoter; |
| 118 binding_.Bind(mojo::MakeRequest(&remoter)); |
| 119 media_router->OnMediaRemoterCreated(kRemotingTabId, std::move(remoter), |
| 120 mojo::MakeRequest(&source_)); |
| 121 } |
| 122 ~MockMediaRemoter() final {} |
| 123 |
| 124 void OnSinkAvailable() { |
| 125 if (source_) |
| 126 source_->OnSinkAvailable(kAllCapabilities); |
| 127 } |
| 128 |
| 129 void SendMessageToSource(const std::vector<uint8_t>& message) { |
| 130 if (source_) |
| 131 source_->OnMessageFromSink(message); |
| 132 } |
| 133 |
| 134 void OnStopped(RemotingStopReason reason) { |
| 135 if (source_) |
| 136 source_->OnStopped(reason); |
| 137 } |
| 138 |
| 139 void OnError() { |
| 140 if (source_) |
| 141 source_->OnError(); |
| 142 } |
| 143 |
| 144 void OnStarted(bool success) { |
| 145 if (source_) { |
| 146 if (success) { |
| 147 source_->OnStarted(); |
| 148 } else { |
| 149 source_->OnStartFailed( |
| 150 RemotingStartFailReason::SERVICE_START_REMOTING_ERROR); |
| 151 } |
| 152 } |
| 153 } |
| 154 |
| 155 MOCK_METHOD0(Start, void()); |
| 156 MOCK_METHOD2(StartDataStreams, void(bool, bool)); |
| 157 MOCK_METHOD1(Stop, void(RemotingStopReason)); |
| 158 MOCK_METHOD1(SendMessageToSink, void(const std::vector<uint8_t>&)); |
| 159 |
| 160 private: |
| 161 mojo::Binding<media::mojom::MirrorServiceRemoter> binding_; |
| 162 MirrorServiceRemotingSourcePtr source_; |
| 163 }; |
| 164 |
237 } // namespace | 165 } // namespace |
238 | 166 |
239 class CastRemotingConnectorTest : public ::testing::Test { | 167 class CastRemotingConnectorTest : public ::testing::Test { |
240 public: | 168 public: |
241 CastRemotingConnectorTest() | 169 CastRemotingConnectorTest() : connector_(&media_router_, kRemotingTabId) { |
242 : connector_(&media_router_, kRemotingMediaSource) { | |
243 // HACK: Override feature flags for testing. | 170 // HACK: Override feature flags for testing. |
244 const_cast<RemotingSinkCapabilities&>(connector_.enabled_features_) = | 171 const_cast<RemotingSinkCapabilities&>(connector_.enabled_features_) = |
245 kAllCapabilities; | 172 kAllCapabilities; |
| 173 |
| 174 EXPECT_EQ(kRemotingTabId, media_router_.tab_id()); |
246 } | 175 } |
247 | 176 |
248 void TearDown() final { | 177 void TearDown() final { |
249 // Allow any pending Mojo operations to complete before destruction. For | 178 // 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 | 179 // 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. | 180 // to later destroy objects that were owned by the message pipe. |
252 RunUntilIdle(); | 181 RunUntilIdle(); |
253 } | 182 } |
254 | 183 |
255 protected: | 184 protected: |
256 RemoterPtr CreateRemoter(MockRemotingSource* source) { | 185 RemoterPtr CreateRemoter(MockRemotingSource* source) { |
257 RemotingSourcePtr source_ptr; | 186 RemotingSourcePtr source_ptr; |
258 source->Bind(mojo::MakeRequest(&source_ptr)); | 187 source->Bind(mojo::MakeRequest(&source_ptr)); |
259 RemoterPtr remoter_ptr; | 188 RemoterPtr remoter_ptr; |
260 connector_.CreateBridge(std::move(source_ptr), | 189 connector_.CreateBridge(std::move(source_ptr), |
261 mojo::MakeRequest(&remoter_ptr)); | 190 mojo::MakeRequest(&remoter_ptr)); |
262 return remoter_ptr; | 191 return remoter_ptr; |
263 } | 192 } |
264 | 193 |
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() { | 194 static void RunUntilIdle() { |
330 base::RunLoop().RunUntilIdle(); | 195 base::RunLoop().RunUntilIdle(); |
331 } | 196 } |
332 | 197 |
| 198 FakeMediaRouter media_router_; |
| 199 |
333 private: | 200 private: |
334 content::TestBrowserThreadBundle browser_thread_bundle_; | 201 content::TestBrowserThreadBundle browser_thread_bundle_; |
335 FakeMediaRouter media_router_; | |
336 CastRemotingConnector connector_; | 202 CastRemotingConnector connector_; |
337 }; | 203 }; |
338 | 204 |
339 TEST_F(CastRemotingConnectorTest, NeverNotifiesThatSinkIsAvailable) { | 205 TEST_F(CastRemotingConnectorTest, NeverNotifiesThatSinkIsAvailable) { |
340 MockRemotingSource source; | 206 MockRemotingSource source; |
341 RemoterPtr remoter = CreateRemoter(&source); | 207 RemoterPtr remoter = CreateRemoter(&source); |
342 | 208 |
343 EXPECT_CALL(source, OnSinkAvailable(_)).Times(0); | 209 EXPECT_CALL(source, OnSinkAvailable(_)).Times(0); |
344 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(0)); | 210 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(0)); |
345 RunUntilIdle(); | 211 RunUntilIdle(); |
346 } | 212 } |
347 | 213 |
348 TEST_F(CastRemotingConnectorTest, NotifiesWhenSinkIsAvailableAndThenGone) { | 214 TEST_F(CastRemotingConnectorTest, NotifiesWhenSinkIsAvailableAndThenGone) { |
349 MockRemotingSource source; | 215 MockRemotingSource source; |
350 RemoterPtr remoter = CreateRemoter(&source); | 216 RemoterPtr remoter = CreateRemoter(&source); |
351 | 217 |
| 218 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 219 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 220 |
352 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); | 221 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); |
353 ProviderDiscoversSink(); | 222 media_remoter->OnSinkAvailable(); |
354 RunUntilIdle(); | 223 RunUntilIdle(); |
355 | 224 |
356 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(1)); | 225 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(1)); |
357 ProviderLosesSink(); | 226 media_remoter.reset(); |
358 RunUntilIdle(); | 227 RunUntilIdle(); |
359 } | 228 } |
360 | 229 |
361 TEST_F(CastRemotingConnectorTest, | 230 TEST_F(CastRemotingConnectorTest, |
362 NotifiesMultipleSourcesWhenSinkIsAvailableAndThenGone) { | 231 NotifiesMultipleSourcesWhenSinkIsAvailableAndThenGone) { |
363 MockRemotingSource source1; | 232 MockRemotingSource source1; |
364 RemoterPtr remoter1 = CreateRemoter(&source1); | 233 RemoterPtr remoter1 = CreateRemoter(&source1); |
365 MockRemotingSource source2; | 234 MockRemotingSource source2; |
366 RemoterPtr remoter2 = CreateRemoter(&source2); | 235 RemoterPtr remoter2 = CreateRemoter(&source2); |
367 | 236 |
| 237 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 238 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 239 |
368 EXPECT_CALL(source1, OnSinkAvailable(kAllCapabilities)).Times(1); | 240 EXPECT_CALL(source1, OnSinkAvailable(kAllCapabilities)).Times(1); |
369 EXPECT_CALL(source2, OnSinkAvailable(kAllCapabilities)).Times(1); | 241 EXPECT_CALL(source2, OnSinkAvailable(kAllCapabilities)).Times(1); |
370 ProviderDiscoversSink(); | 242 media_remoter->OnSinkAvailable(); |
371 RunUntilIdle(); | 243 RunUntilIdle(); |
372 | 244 |
373 EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1)); | 245 EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1)); |
374 EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1)); | 246 EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1)); |
375 ProviderLosesSink(); | 247 media_remoter.reset(); |
376 RunUntilIdle(); | 248 RunUntilIdle(); |
377 } | 249 } |
378 | 250 |
379 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemotingSourceFirst) { | 251 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemotingSourceFirst) { |
380 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource); | 252 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource); |
381 RemoterPtr remoter = CreateRemoter(source.get()); | 253 RemoterPtr remoter = CreateRemoter(source.get()); |
382 | 254 |
| 255 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 256 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 257 |
383 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1); | 258 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1); |
384 ProviderDiscoversSink(); | 259 media_remoter->OnSinkAvailable(); |
385 RunUntilIdle(); | 260 RunUntilIdle(); |
386 | 261 |
387 source.reset(); | 262 source.reset(); |
388 RunUntilIdle(); | 263 RunUntilIdle(); |
389 } | 264 } |
390 | 265 |
391 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemoterFirst) { | 266 TEST_F(CastRemotingConnectorTest, HandlesTeardownOfRemoterFirst) { |
392 MockRemotingSource source; | 267 MockRemotingSource source; |
393 RemoterPtr remoter = CreateRemoter(&source); | 268 RemoterPtr remoter = CreateRemoter(&source); |
394 | 269 |
| 270 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 271 base::MakeUnique<MockMediaRemoter>(&media_router_); |
| 272 |
395 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); | 273 EXPECT_CALL(source, OnSinkAvailable(kAllCapabilities)).Times(1); |
396 ProviderDiscoversSink(); | 274 media_remoter->OnSinkAvailable(); |
397 RunUntilIdle(); | 275 RunUntilIdle(); |
398 | 276 |
399 remoter.reset(); | 277 remoter.reset(); |
400 RunUntilIdle(); | 278 RunUntilIdle(); |
401 } | 279 } |
402 | 280 |
| 281 TEST_F(CastRemotingConnectorTest, NoConnectedMediaRemoter) { |
| 282 MockRemotingSource source; |
| 283 RemoterPtr remoter = CreateRemoter(&source); |
| 284 |
| 285 EXPECT_CALL(source, |
| 286 OnStartFailed(RemotingStartFailReason::SERVICE_NOT_CONNECTED)) |
| 287 .Times(1); |
| 288 remoter->Start(); |
| 289 RunUntilIdle(); |
| 290 } |
| 291 |
403 namespace { | 292 namespace { |
404 | 293 |
405 // The possible ways a remoting session may be terminated in the "full | 294 // The possible ways a remoting session may be terminated in the "full |
406 // run-through" tests. | 295 // run-through" tests. |
407 enum HowItEnds { | 296 enum HowItEnds { |
408 SOURCE_TERMINATES, // The render process decides to end remoting. | 297 SOURCE_TERMINATES, // The render process decides to end remoting. |
409 MOJO_PIPE_CLOSES, // A Mojo message pipe closes unexpectedly. | 298 MOJO_PIPE_CLOSES, // A Mojo message pipe closes unexpectedly. |
410 ROUTE_TERMINATES, // The Media Router UI was used to terminate the route. | 299 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. | 300 EXTERNAL_FAILURE, // The sink is cut-off, perhaps due to a network outage. |
412 }; | 301 }; |
413 | 302 |
414 } // namespace | 303 } // namespace |
415 | 304 |
416 class CastRemotingConnectorFullSessionTest | 305 class CastRemotingConnectorFullSessionTest |
417 : public CastRemotingConnectorTest, | 306 : public CastRemotingConnectorTest, |
418 public ::testing::WithParamInterface<HowItEnds> { | 307 public ::testing::WithParamInterface<HowItEnds> { |
419 public: | 308 public: |
420 HowItEnds how_it_ends() const { return GetParam(); } | 309 HowItEnds how_it_ends() const { return GetParam(); } |
421 }; | 310 }; |
422 | 311 |
423 // Performs a full run-through of starting and stopping remoting, with | 312 // Performs a full run-through of starting and stopping remoting, with |
424 // communications between source and sink established at the correct times, and | 313 // 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 | 314 // tests that end-to-end behavior is correct depending on what caused the |
426 // remoting session to end. | 315 // remoting session to end. |
427 TEST_P(CastRemotingConnectorFullSessionTest, GoesThroughAllTheMotions) { | 316 TEST_P(CastRemotingConnectorFullSessionTest, GoesThroughAllTheMotions) { |
428 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource()); | 317 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource()); |
429 RemoterPtr remoter = CreateRemoter(source.get()); | 318 RemoterPtr remoter = CreateRemoter(source.get()); |
430 std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource()); | 319 std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource()); |
431 RemoterPtr other_remoter = CreateRemoter(other_source.get()); | 320 RemoterPtr other_remoter = CreateRemoter(other_source.get()); |
| 321 std::unique_ptr<MockMediaRemoter> media_remoter = |
| 322 base::MakeUnique<MockMediaRemoter>(&media_router_); |
432 | 323 |
433 // Throughout this test |other_source| should not participate in the | 324 // Throughout this test |other_source| should not participate in the |
434 // remoting session, and so these method calls should never occur: | 325 // remoting session, and so these method calls should never occur: |
435 EXPECT_CALL(*other_source, OnStarted()).Times(0); | 326 EXPECT_CALL(*other_source, OnStarted()).Times(0); |
436 EXPECT_CALL(*other_source, OnStopped(_)).Times(0); | 327 EXPECT_CALL(*other_source, OnStopped(_)).Times(0); |
437 EXPECT_CALL(*other_source, OnMessageFromSink(_)).Times(0); | 328 EXPECT_CALL(*other_source, OnMessageFromSink(_)).Times(0); |
438 | 329 |
439 // Both sinks should be notified when the Cast Provider tells the connector | 330 // Both sinks should be notified when the Cast Provider tells the connector |
440 // a remoting sink is available. | 331 // a remoting sink is available. |
441 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) | 332 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) |
442 .RetiresOnSaturation(); | 333 .RetiresOnSaturation(); |
443 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) | 334 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) |
444 .RetiresOnSaturation(); | 335 .RetiresOnSaturation(); |
445 ProviderDiscoversSink(); | 336 media_remoter->OnSinkAvailable(); |
446 RunUntilIdle(); | 337 RunUntilIdle(); |
447 | 338 |
448 // When |source| starts a remoting session, |other_source| is notified the | 339 // When |source| starts a remoting session, |other_source| is notified the |
449 // sink is gone, the Cast Provider is notified that remoting has started, | 340 // sink is gone, the Cast Provider is notified that remoting has started, |
450 // and |source| is notified that its request was successful. | 341 // and |source| is notified that its request was successful. |
451 EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation(); | |
452 EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation(); | 342 EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation(); |
| 343 EXPECT_CALL(*media_remoter, Start()).Times(1).RetiresOnSaturation(); |
453 remoter->Start(); | 344 remoter->Start(); |
454 RunUntilIdle(); | 345 RunUntilIdle(); |
455 ConnectorSentMessageToProvider("START_CAST_REMOTING:session=1"); | 346 EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation(); |
| 347 media_remoter->OnStarted(true); |
| 348 RunUntilIdle(); |
456 | 349 |
457 // The |source| should now be able to send binary messages to the sink. | 350 // The |source| should now be able to send binary messages to the sink. |
458 // |other_source| should not! | 351 // |other_source| should not! |
459 const std::vector<uint8_t> message_to_sink = { 3, 1, 4, 1, 5, 9 }; | 352 const std::vector<uint8_t> message_to_sink = { 3, 1, 4, 1, 5, 9 }; |
| 353 EXPECT_CALL(*media_remoter, SendMessageToSink(message_to_sink)) |
| 354 .Times(1) |
| 355 .RetiresOnSaturation(); |
460 remoter->SendMessageToSink(message_to_sink); | 356 remoter->SendMessageToSink(message_to_sink); |
461 const std::vector<uint8_t> ignored_message_to_sink = { 1, 2, 3 }; | 357 const std::vector<uint8_t> ignored_message_to_sink = { 1, 2, 3 }; |
| 358 EXPECT_CALL(*media_remoter, SendMessageToSink(ignored_message_to_sink)) |
| 359 .Times(0); |
462 other_remoter->SendMessageToSink(ignored_message_to_sink); | 360 other_remoter->SendMessageToSink(ignored_message_to_sink); |
463 RunUntilIdle(); | 361 RunUntilIdle(); |
464 ConnectorSentMessageToSink(message_to_sink); | |
465 | 362 |
466 // The sink should also be able to send binary messages to the |source|. | 363 // 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 }; | 364 const std::vector<uint8_t> message_to_source = { 2, 7, 1, 8, 2, 8 }; |
468 EXPECT_CALL(*source, OnMessageFromSink(message_to_source)).Times(1) | 365 EXPECT_CALL(*source, OnMessageFromSink(message_to_source)).Times(1) |
469 .RetiresOnSaturation(); | 366 .RetiresOnSaturation(); |
470 ProviderPassesMessageFromSink(message_to_source); | 367 media_remoter->SendMessageToSource(message_to_source); |
471 RunUntilIdle(); | 368 RunUntilIdle(); |
472 | 369 |
473 // The |other_source| should not be allowed to start a remoting session. | 370 // The |other_source| should not be allowed to start a remoting session. |
474 EXPECT_CALL(*other_source, | 371 EXPECT_CALL(*other_source, |
475 OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE)) | 372 OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE)) |
476 .Times(1).RetiresOnSaturation(); | 373 .Times(1).RetiresOnSaturation(); |
477 other_remoter->Start(); | 374 other_remoter->Start(); |
478 RunUntilIdle(); | 375 RunUntilIdle(); |
479 ConnectorSentNoMessagesToProvider(); | |
480 | 376 |
481 // What happens from here depends on how this remoting session will end... | 377 // What happens from here depends on how this remoting session will end... |
482 switch (how_it_ends()) { | 378 switch (how_it_ends()) { |
483 case SOURCE_TERMINATES: { | 379 case SOURCE_TERMINATES: { |
484 // When the |source| stops the remoting session, the Cast Provider is | 380 // When the |source| stops the remoting session, the Cast Provider is |
485 // notified the session has stopped, and the |source| receives both an | 381 // notified the session has stopped, and the |source| receives both an |
486 // OnStopped() and an OnSinkGone() notification. | 382 // OnStopped() and an OnSinkGone() notification. |
487 const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK; | 383 const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK; |
488 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); | 384 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); |
489 EXPECT_CALL(*source, OnStopped(reason)).Times(1).RetiresOnSaturation(); | 385 EXPECT_CALL(*source, OnStopped(reason)).Times(1).RetiresOnSaturation(); |
| 386 EXPECT_CALL(*media_remoter, Stop(reason)).Times(1).RetiresOnSaturation(); |
490 remoter->Stop(reason); | 387 remoter->Stop(reason); |
491 RunUntilIdle(); | 388 RunUntilIdle(); |
492 ConnectorSentMessageToProvider("STOP_CAST_REMOTING:session=1"); | |
493 | 389 |
494 // Since remoting is stopped, any further messaging in either direction | 390 // Since remoting is stopped, any further messaging in either direction |
495 // must be dropped. | 391 // must be dropped. |
496 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; | 392 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 }; | 393 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; |
498 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); | 394 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); |
| 395 EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); |
499 remoter->SendMessageToSink(message_to_sink); | 396 remoter->SendMessageToSink(message_to_sink); |
500 ProviderPassesMessageFromSink(message_to_source); | 397 media_remoter->SendMessageToSource(message_to_source); |
501 RunUntilIdle(); | 398 RunUntilIdle(); |
502 ConnectorSentNoMessagesToSink(); | |
503 | 399 |
504 // When the sink is ready, the Cast Provider sends a notification to the | 400 // 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 | 401 // connector. The connector will notify both sources that a sink is once |
506 // again available. | 402 // again available. |
507 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) | 403 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) |
508 .RetiresOnSaturation(); | 404 .RetiresOnSaturation(); |
509 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) | 405 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) |
510 .RetiresOnSaturation(); | 406 .RetiresOnSaturation(); |
511 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); | 407 media_remoter->OnStopped(reason); |
512 RunUntilIdle(); | 408 RunUntilIdle(); |
513 | 409 |
514 // When the sink is no longer available, the Cast Provider notifies the | 410 // When the sink is no longer available, the Cast Provider notifies the |
515 // connector, and both sources are then notified the sink is gone. | 411 // connector, and both sources are then notified the sink is gone. |
516 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); | 412 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); |
517 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); | 413 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); |
518 ProviderLosesSink(); | 414 media_remoter.reset(); |
519 RunUntilIdle(); | 415 RunUntilIdle(); |
520 | 416 |
521 break; | 417 break; |
522 } | 418 } |
523 | 419 |
524 case MOJO_PIPE_CLOSES: | 420 case MOJO_PIPE_CLOSES: |
525 // When the Mojo pipes for |other_source| close, this should not affect | 421 // When the Mojo pipes for |other_source| close, this should not affect |
526 // the current remoting session. | 422 // the current remoting session. |
| 423 EXPECT_CALL(*media_remoter, Stop(_)).Times(0); |
527 other_source.reset(); | 424 other_source.reset(); |
528 other_remoter.reset(); | 425 other_remoter.reset(); |
529 RunUntilIdle(); | 426 RunUntilIdle(); |
530 ConnectorSentNoMessagesToProvider(); | |
531 | 427 |
532 // Now, when the Mojo pipes for |source| close, the Cast Provider will be | 428 // Now, when the Mojo pipes for |source| close, the Cast Provider will be |
533 // notified that the session has stopped. | 429 // notified that the session has stopped. |
| 430 EXPECT_CALL(*media_remoter, Stop(_)).Times(1).RetiresOnSaturation(); |
534 source.reset(); | 431 source.reset(); |
535 remoter.reset(); | 432 remoter.reset(); |
536 RunUntilIdle(); | 433 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 | 434 |
545 break; | 435 break; |
546 | 436 |
547 case ROUTE_TERMINATES: | 437 case ROUTE_TERMINATES: |
548 // When the Media Router terminates the route (e.g., because a user | 438 // 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 | 439 // terminated the route from the UI), the source and sink are immediately |
550 // cut off from one another. | 440 // cut off from one another. |
551 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); | 441 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)); | 442 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 | 443 // Furthermore, the connector and Cast Provider are also cut off from one |
560 // another and should not be able to exchange messages anymore. Therefore, | 444 // 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 | 445 // the connector will never try to notify the sources that the sink is |
562 // available again. | 446 // available again. |
563 EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); | 447 EXPECT_CALL(*source, OnSinkAvailable(_)).Times(0); |
564 EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); | 448 EXPECT_CALL(*other_source, OnSinkAvailable(_)).Times(0); |
565 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); | 449 media_remoter.reset(); |
566 RunUntilIdle(); | 450 RunUntilIdle(); |
567 | 451 |
568 break; | 452 break; |
569 | 453 |
570 case EXTERNAL_FAILURE: { | 454 case EXTERNAL_FAILURE: { |
571 // When the Cast Provider is cut-off from the sink, it sends a fail | 455 // 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 | 456 // notification to the connector. The connector, in turn, force-stops the |
573 // remoting session and notifies the |source|. | 457 // remoting session and notifies the |source|. |
574 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); | 458 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation(); |
575 EXPECT_CALL(*source, OnStopped(RemotingStopReason::UNEXPECTED_FAILURE)) | 459 EXPECT_CALL(*source, OnStopped(RemotingStopReason::UNEXPECTED_FAILURE)) |
576 .Times(1).RetiresOnSaturation(); | 460 .Times(1).RetiresOnSaturation(); |
577 ProviderSaysToRemotingConnector("FAILED_CAST_REMOTING:session=1"); | 461 EXPECT_CALL(*media_remoter, Stop(RemotingStopReason::UNEXPECTED_FAILURE)) |
| 462 .Times(1) |
| 463 .RetiresOnSaturation(); |
| 464 media_remoter->OnError(); |
578 RunUntilIdle(); | 465 RunUntilIdle(); |
579 | 466 |
580 // Since remoting is stopped, any further messaging in either direction | 467 // Since remoting is stopped, any further messaging in either direction |
581 // must be dropped. | 468 // must be dropped. |
582 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 }; | 469 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 }; | 470 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 }; |
584 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); | 471 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0); |
| 472 EXPECT_CALL(*media_remoter, SendMessageToSink(_)).Times(0); |
585 remoter->SendMessageToSink(message_to_sink); | 473 remoter->SendMessageToSink(message_to_sink); |
586 ProviderPassesMessageFromSink(message_to_source); | 474 media_remoter->SendMessageToSource(message_to_source); |
587 RunUntilIdle(); | 475 RunUntilIdle(); |
588 ConnectorSentNoMessagesToSink(); | |
589 | 476 |
590 // Later, if whatever caused the external failure has resolved, the Cast | 477 // Later, if whatever caused the external failure has resolved, the Cast |
591 // Provider will notify the connector that the sink is available one | 478 // Provider will notify the connector that the sink is available one |
592 // again. | 479 // again. |
593 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) | 480 EXPECT_CALL(*source, OnSinkAvailable(kAllCapabilities)).Times(1) |
594 .RetiresOnSaturation(); | 481 .RetiresOnSaturation(); |
595 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) | 482 EXPECT_CALL(*other_source, OnSinkAvailable(kAllCapabilities)).Times(1) |
596 .RetiresOnSaturation(); | 483 .RetiresOnSaturation(); |
597 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1"); | 484 media_remoter->OnStopped(RemotingStopReason::UNEXPECTED_FAILURE); |
598 RunUntilIdle(); | 485 RunUntilIdle(); |
599 | 486 |
600 // When the sink is no longer available, the Cast Provider notifies the | 487 // When the sink is no longer available, the Cast Provider notifies the |
601 // connector, and both sources are then notified the sink is gone. | 488 // connector, and both sources are then notified the sink is gone. |
602 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); | 489 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1)); |
603 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); | 490 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1)); |
604 ProviderLosesSink(); | 491 media_remoter.reset(); |
605 RunUntilIdle(); | 492 RunUntilIdle(); |
606 | 493 |
607 break; | 494 break; |
608 } | 495 } |
609 } | 496 } |
610 } | 497 } |
611 | 498 |
612 INSTANTIATE_TEST_CASE_P(, CastRemotingConnectorFullSessionTest, | 499 INSTANTIATE_TEST_CASE_P(, CastRemotingConnectorFullSessionTest, |
613 ::testing::Values(SOURCE_TERMINATES, | 500 ::testing::Values(SOURCE_TERMINATES, |
614 MOJO_PIPE_CLOSES, | 501 MOJO_PIPE_CLOSES, |
615 ROUTE_TERMINATES, | 502 ROUTE_TERMINATES, |
616 EXTERNAL_FAILURE)); | 503 EXTERNAL_FAILURE)); |
OLD | NEW |