Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: chrome/browser/media/cast_remoting_connector.cc

Issue 2951523002: Media Remoting: Add mojo interfaces between browser and extension. (Closed)
Patch Set: Fix unittests. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
13 #include "chrome/browser/media/cast_remoting_connector_messaging.h"
14 #include "chrome/browser/media/cast_remoting_sender.h" 13 #include "chrome/browser/media/cast_remoting_sender.h"
15 #include "chrome/browser/media/router/media_router.h" 14 #include "chrome/browser/media/router/media_router.h"
16 #include "chrome/browser/media/router/media_router_factory.h" 15 #include "chrome/browser/media/router/media_router_factory.h"
17 #include "chrome/browser/media/router/route_message_observer.h"
18 #include "chrome/browser/sessions/session_tab_helper.h" 16 #include "chrome/browser/sessions/session_tab_helper.h"
19 #include "chrome/common/chrome_features.h" 17 #include "chrome/common/chrome_features.h"
20 #include "chrome/common/media_router/media_source_helper.h"
21 #include "chrome/common/media_router/route_message.h"
22 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/render_frame_host.h" 19 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/render_process_host.h" 20 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents.h"
26 #include "mojo/public/cpp/bindings/strong_binding.h" 22 #include "mojo/public/cpp/bindings/strong_binding.h"
27 23
28 using content::BrowserThread; 24 using content::BrowserThread;
29 using media::mojom::RemotingSinkCapabilities; 25 using media::mojom::RemotingSinkCapabilities;
30 using media::mojom::RemotingStartFailReason; 26 using media::mojom::RemotingStartFailReason;
31 using media::mojom::RemotingStopReason; 27 using media::mojom::RemotingStopReason;
32 28
33 using Messaging = CastRemotingConnectorMessaging;
34
35 class CastRemotingConnector::RemotingBridge : public media::mojom::Remoter { 29 class CastRemotingConnector::RemotingBridge : public media::mojom::Remoter {
36 public: 30 public:
37 // Constructs a "bridge" to delegate calls between the given |source| and 31 // Constructs a "bridge" to delegate calls between the given |source| and
38 // |connector|. |connector| must be valid at the time of construction, but is 32 // |connector|. |connector| must be valid at the time of construction, but is
39 // otherwise a weak pointer that can become invalid during the lifetime of a 33 // otherwise a weak pointer that can become invalid during the lifetime of a
40 // RemotingBridge. 34 // RemotingBridge.
41 RemotingBridge(media::mojom::RemotingSourcePtr source, 35 RemotingBridge(media::mojom::RemotingSourcePtr source,
42 CastRemotingConnector* connector) 36 CastRemotingConnector* connector)
43 : source_(std::move(source)), connector_(connector) { 37 : source_(std::move(source)), connector_(connector) {
44 DCHECK(connector_); 38 DCHECK(connector_);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 private: 99 private:
106 media::mojom::RemotingSourcePtr source_; 100 media::mojom::RemotingSourcePtr source_;
107 101
108 // Weak pointer. Will be set to nullptr if the CastRemotingConnector is 102 // Weak pointer. Will be set to nullptr if the CastRemotingConnector is
109 // destroyed before this RemotingBridge. 103 // destroyed before this RemotingBridge.
110 CastRemotingConnector* connector_; 104 CastRemotingConnector* connector_;
111 105
112 DISALLOW_COPY_AND_ASSIGN(RemotingBridge); 106 DISALLOW_COPY_AND_ASSIGN(RemotingBridge);
113 }; 107 };
114 108
115 class CastRemotingConnector::MessageObserver
116 : public media_router::RouteMessageObserver {
117 public:
118 MessageObserver(media_router::MediaRouter* router,
119 const media_router::MediaRoute::Id& route_id,
120 CastRemotingConnector* connector)
121 : RouteMessageObserver(router, route_id), connector_(connector) {}
122 ~MessageObserver() final {}
123
124 private:
125 void OnMessagesReceived(
126 const std::vector<media_router::RouteMessage>& messages) final {
127 connector_->ProcessMessagesFromRoute(messages);
128 }
129
130 CastRemotingConnector* const connector_;
131 };
132
133 // static 109 // static
134 const void* const CastRemotingConnector::kUserDataKey = &kUserDataKey; 110 const void* const CastRemotingConnector::kUserDataKey = &kUserDataKey;
135 111
136 // static 112 // static
137 CastRemotingConnector* CastRemotingConnector::Get( 113 CastRemotingConnector* CastRemotingConnector::Get(
138 content::WebContents* contents) { 114 content::WebContents* contents) {
139 DCHECK(contents); 115 DCHECK(contents);
140 CastRemotingConnector* connector = 116 CastRemotingConnector* connector =
141 static_cast<CastRemotingConnector*>(contents->GetUserData(kUserDataKey)); 117 static_cast<CastRemotingConnector*>(contents->GetUserData(kUserDataKey));
142 if (!connector) { 118 if (!connector) {
119 const SessionID::id_type tab_id = SessionTabHelper::IdForTab(contents);
imcheng 2017/07/05 18:53:08 FYI: MediaRouterAndroid use TabAndroid::GetAndroid
xjz 2017/07/06 22:03:44 Done.
120 if (tab_id == -1)
121 return nullptr;
143 connector = new CastRemotingConnector( 122 connector = new CastRemotingConnector(
144 media_router::MediaRouterFactory::GetApiForBrowserContext( 123 media_router::MediaRouterFactory::GetApiForBrowserContext(
145 contents->GetBrowserContext()), 124 contents->GetBrowserContext()),
146 media_router::MediaSourceForTabContentRemoting( 125 tab_id);
147 SessionTabHelper::IdForTab(contents))
148 .id());
149 contents->SetUserData(kUserDataKey, base::WrapUnique(connector)); 126 contents->SetUserData(kUserDataKey, base::WrapUnique(connector));
150 } 127 }
151 return connector; 128 return connector;
152 } 129 }
153 130
154 // static 131 // static
155 void CastRemotingConnector::CreateMediaRemoter( 132 void CastRemotingConnector::CreateMediaRemoter(
156 content::RenderFrameHost* host, 133 content::RenderFrameHost* host,
157 media::mojom::RemotingSourcePtr source, 134 media::mojom::RemotingSourcePtr source,
158 media::mojom::RemoterRequest request) { 135 media::mojom::RemoterRequest request) {
159 DCHECK(host); 136 DCHECK(host);
160 auto* const contents = content::WebContents::FromRenderFrameHost(host); 137 auto* const contents = content::WebContents::FromRenderFrameHost(host);
161 if (!contents) 138 if (!contents)
162 return; 139 return;
163 CastRemotingConnector::Get(contents)->CreateBridge(std::move(source), 140 CastRemotingConnector* const connector = CastRemotingConnector::Get(contents);
164 std::move(request)); 141 if (!connector)
142 return;
143 connector->CreateBridge(std::move(source), std::move(request));
165 } 144 }
166 145
167 namespace { 146 namespace {
168 RemotingSinkCapabilities GetFeatureEnabledCapabilities() { 147 RemotingSinkCapabilities GetFeatureEnabledCapabilities() {
169 #if !defined(OS_ANDROID) && !defined(OS_IOS) 148 #if !defined(OS_ANDROID) && !defined(OS_IOS)
170 if (base::FeatureList::IsEnabled(features::kMediaRemoting)) { 149 if (base::FeatureList::IsEnabled(features::kMediaRemoting)) {
171 return RemotingSinkCapabilities::RENDERING_ONLY; 150 return RemotingSinkCapabilities::RENDERING_ONLY;
172 } 151 }
173 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) 152 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
174 return RemotingSinkCapabilities::NONE; 153 return RemotingSinkCapabilities::NONE;
175 } 154 }
176 } // namespace 155 } // namespace
177 156
178 CastRemotingConnector::CastRemotingConnector( 157 CastRemotingConnector::CastRemotingConnector(media_router::MediaRouter* router,
179 media_router::MediaRouter* router, 158 int32_t tab_id)
180 const media_router::MediaSource::Id& media_source_id) 159 : media_router_(router),
181 : media_router::MediaRoutesObserver(router), 160 tab_id_(tab_id),
182 media_source_id_(media_source_id),
183 enabled_features_(GetFeatureEnabledCapabilities()), 161 enabled_features_(GetFeatureEnabledCapabilities()),
184 session_counter_(0),
185 active_bridge_(nullptr), 162 active_bridge_(nullptr),
186 weak_factory_(this) {} 163 binding_(this),
164 weak_factory_(this) {
165 VLOG(2) << "Register CastRemotingConnector for tab_id = " << tab_id_;
166 media_router_->RegisterRemotingSource(tab_id_, this);
167 }
187 168
188 CastRemotingConnector::~CastRemotingConnector() { 169 CastRemotingConnector::~CastRemotingConnector() {
189 // Assume nothing about destruction/shutdown sequence of a tab. For example, 170 // Assume nothing about destruction/shutdown sequence of a tab. For example,
190 // it's possible the owning WebContents will be destroyed before the Mojo 171 // it's possible the owning WebContents will be destroyed before the Mojo
191 // message pipes to the RemotingBridges have been closed. 172 // message pipes to the RemotingBridges have been closed.
192 if (active_bridge_) 173 if (active_bridge_)
193 StopRemoting(active_bridge_, RemotingStopReason::ROUTE_TERMINATED); 174 StopRemoting(active_bridge_, RemotingStopReason::ROUTE_TERMINATED);
194 for (RemotingBridge* notifyee : bridges_) { 175 for (RemotingBridge* notifyee : bridges_) {
195 notifyee->OnSinkGone(); 176 notifyee->OnSinkGone();
196 notifyee->OnCastRemotingConnectorDestroyed(); 177 notifyee->OnCastRemotingConnectorDestroyed();
197 } 178 }
179 media_router_->UnregisterRemotingSource(tab_id_);
180 }
181
182 void CastRemotingConnector::ConnectToService(
183 media::mojom::MirrorServiceRemotingSourceRequest source_request,
184 media::mojom::MirrorServiceRemoterPtr remoter) {
185 DCHECK(!binding_.is_bound());
186 DCHECK(!remoter_);
187 DCHECK(remoter);
188 DCHECK_CURRENTLY_ON(BrowserThread::UI);
189 VLOG(2) << __func__;
190
191 binding_.Bind(std::move(source_request));
192 binding_.set_connection_error_handler(base::Bind(
193 &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this)));
194 remoter_ = std::move(remoter);
195 remoter_.set_connection_error_handler(base::Bind(
196 &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this)));
197 }
198
199 void CastRemotingConnector::OnMirrorServiceStopped() {
200 DCHECK_CURRENTLY_ON(BrowserThread::UI);
201 VLOG(2) << __func__;
202
203 if (binding_.is_bound())
204 binding_.Close();
205 remoter_.reset();
206
207 if (active_bridge_)
208 StopRemoting(active_bridge_, RemotingStopReason::SERVICE_GONE);
209 for (RemotingBridge* notifyee : bridges_)
210 notifyee->OnSinkGone();
198 } 211 }
199 212
200 void CastRemotingConnector::CreateBridge(media::mojom::RemotingSourcePtr source, 213 void CastRemotingConnector::CreateBridge(media::mojom::RemotingSourcePtr source,
201 media::mojom::RemoterRequest request) { 214 media::mojom::RemoterRequest request) {
202 mojo::MakeStrongBinding( 215 mojo::MakeStrongBinding(
203 base::MakeUnique<RemotingBridge>(std::move(source), this), 216 base::MakeUnique<RemotingBridge>(std::move(source), this),
204 std::move(request)); 217 std::move(request));
205 } 218 }
206 219
207 void CastRemotingConnector::RegisterBridge(RemotingBridge* bridge) { 220 void CastRemotingConnector::RegisterBridge(RemotingBridge* bridge) {
208 DCHECK_CURRENTLY_ON(BrowserThread::UI); 221 DCHECK_CURRENTLY_ON(BrowserThread::UI);
209 DCHECK(bridges_.find(bridge) == bridges_.end()); 222 DCHECK(bridges_.find(bridge) == bridges_.end());
210 223
211 bridges_.insert(bridge); 224 bridges_.insert(bridge);
212 if (message_observer_ && !active_bridge_) 225 // TODO(xjz): Pass the receiver's capabilities to the source.
226 if (remoter_ && !active_bridge_)
213 bridge->OnSinkAvailable(enabled_features_); 227 bridge->OnSinkAvailable(enabled_features_);
214 } 228 }
215 229
216 void CastRemotingConnector::DeregisterBridge(RemotingBridge* bridge, 230 void CastRemotingConnector::DeregisterBridge(RemotingBridge* bridge,
217 RemotingStopReason reason) { 231 RemotingStopReason reason) {
218 DCHECK_CURRENTLY_ON(BrowserThread::UI); 232 DCHECK_CURRENTLY_ON(BrowserThread::UI);
219 DCHECK(bridges_.find(bridge) != bridges_.end()); 233 DCHECK(bridges_.find(bridge) != bridges_.end());
220 234
221 if (bridge == active_bridge_) 235 if (bridge == active_bridge_)
222 StopRemoting(bridge, reason); 236 StopRemoting(bridge, reason);
223 bridges_.erase(bridge); 237 bridges_.erase(bridge);
224 } 238 }
225 239
226 void CastRemotingConnector::StartRemoting(RemotingBridge* bridge) { 240 void CastRemotingConnector::StartRemoting(RemotingBridge* bridge) {
227 DCHECK_CURRENTLY_ON(BrowserThread::UI); 241 DCHECK_CURRENTLY_ON(BrowserThread::UI);
228 DCHECK(bridges_.find(bridge) != bridges_.end()); 242 DCHECK(bridges_.find(bridge) != bridges_.end());
243 VLOG(2) << __func__;
229 244
230 // Refuse to start if there is no remoting route available, or if remoting is 245 // Refuse to start if there is no remoting route available, or if remoting is
231 // already active. 246 // already active.
232 if (!message_observer_) { 247 if (!remoter_) {
233 bridge->OnStartFailed(RemotingStartFailReason::ROUTE_TERMINATED); 248 VLOG(2) << "Remoting start failed: No mirror service connected.";
249 bridge->OnStartFailed(RemotingStartFailReason::SERVICE_NOT_CONNECTED);
234 return; 250 return;
235 } 251 }
236 if (active_bridge_) { 252 if (active_bridge_) {
253 VLOG(2) << "Remoting start failed: Cannot start multiple.";
237 bridge->OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE); 254 bridge->OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE);
238 return; 255 return;
239 } 256 }
240 257
241 // Notify all other sources that the sink is no longer available for remoting. 258 // Notify all other sources that the sink is no longer available for remoting.
242 // A race condition is possible, where one of the other sources will try to 259 // A race condition is possible, where one of the other sources will try to
243 // start remoting before receiving this notification; but that attempt will 260 // start remoting before receiving this notification; but that attempt will
244 // just fail later on. 261 // just fail later on.
245 for (RemotingBridge* notifyee : bridges_) { 262 for (RemotingBridge* notifyee : bridges_) {
246 if (notifyee == bridge) 263 if (notifyee == bridge)
247 continue; 264 continue;
248 notifyee->OnSinkGone(); 265 notifyee->OnSinkGone();
249 } 266 }
250 267
251 active_bridge_ = bridge; 268 active_bridge_ = bridge;
269 remoter_->Start();
252 270
253 // Send a start message to the Cast Provider. 271 // Assume the remoting session is always started successfully. If any failure
254 ++session_counter_; // New remoting session ID. 272 // occurs, OnError() will be called.
255 SendMessageToProvider(base::StringPrintf(
256 Messaging::kStartRemotingMessageFormat, session_counter_));
257
258 bridge->OnStarted(); 273 bridge->OnStarted();
259 } 274 }
260 275
261 void CastRemotingConnector::StartRemotingDataStreams( 276 void CastRemotingConnector::StartRemotingDataStreams(
262 RemotingBridge* bridge, 277 RemotingBridge* bridge,
263 mojo::ScopedDataPipeConsumerHandle audio_pipe, 278 mojo::ScopedDataPipeConsumerHandle audio_pipe,
264 mojo::ScopedDataPipeConsumerHandle video_pipe, 279 mojo::ScopedDataPipeConsumerHandle video_pipe,
265 media::mojom::RemotingDataStreamSenderRequest audio_sender_request, 280 media::mojom::RemotingDataStreamSenderRequest audio_sender_request,
266 media::mojom::RemotingDataStreamSenderRequest video_sender_request) { 281 media::mojom::RemotingDataStreamSenderRequest video_sender_request) {
267 DCHECK_CURRENTLY_ON(BrowserThread::UI); 282 DCHECK_CURRENTLY_ON(BrowserThread::UI);
283 VLOG(2) << __func__;
268 284
269 // Refuse to start if there is no remoting route available, or if remoting is 285 // Refuse to start if there is no remoting route available, or if remoting is
270 // not active for this |bridge|. 286 // not active for this |bridge|.
271 if (!message_observer_ || active_bridge_ != bridge) 287 if (!remoter_ || active_bridge_ != bridge)
272 return; 288 return;
273 // Also, if neither audio nor video pipe was provided, or if a request for a 289 // Also, if neither audio nor video pipe was provided, or if a request for a
274 // RemotingDataStreamSender was not provided for a data pipe, error-out early. 290 // RemotingDataStreamSender was not provided for a data pipe, error-out early.
275 if ((!audio_pipe.is_valid() && !video_pipe.is_valid()) || 291 if ((!audio_pipe.is_valid() && !video_pipe.is_valid()) ||
276 (audio_pipe.is_valid() && !audio_sender_request.is_pending()) || 292 (audio_pipe.is_valid() && !audio_sender_request.is_pending()) ||
277 (video_pipe.is_valid() && !video_sender_request.is_pending())) { 293 (video_pipe.is_valid() && !video_sender_request.is_pending())) {
278 StopRemoting(active_bridge_, RemotingStopReason::DATA_SEND_FAILED); 294 StopRemoting(active_bridge_, RemotingStopReason::DATA_SEND_FAILED);
279 return; 295 return;
280 } 296 }
281 297
282 // Hold on to the data pipe handles and interface requests until one/both 298 const bool want_audio = audio_sender_request.is_pending();
283 // CastRemotingSenders are created and ready for use. 299 const bool want_video = video_sender_request.is_pending();
284 pending_audio_pipe_ = std::move(audio_pipe); 300 remoter_->StartDataStreams(
285 pending_video_pipe_ = std::move(video_pipe); 301 want_audio, want_video,
286 pending_audio_sender_request_ = std::move(audio_sender_request); 302 base::BindOnce(&CastRemotingConnector::OnDataStreamsStarted,
287 pending_video_sender_request_ = std::move(video_sender_request); 303 weak_factory_.GetWeakPtr(), std::move(audio_pipe),
304 std::move(video_pipe), std::move(audio_sender_request),
305 std::move(video_sender_request)));
306 }
288 307
289 // Send a "start streams" message to the Cast Provider. The provider is 308 void CastRemotingConnector::OnDataStreamsStarted(
290 // responsible for creating and setting up a remoting Cast Streaming session 309 mojo::ScopedDataPipeConsumerHandle audio_pipe,
291 // that will result in new CastRemotingSender instances being created here in 310 mojo::ScopedDataPipeConsumerHandle video_pipe,
292 // the browser process. 311 media::mojom::RemotingDataStreamSenderRequest audio_sender_request,
293 SendMessageToProvider(base::StringPrintf( 312 media::mojom::RemotingDataStreamSenderRequest video_sender_request,
294 Messaging::kStartStreamsMessageFormat, session_counter_, 313 int32_t audio_stream_id,
295 pending_audio_sender_request_.is_pending() ? 'Y' : 'N', 314 int32_t video_stream_id) {
296 pending_video_sender_request_.is_pending() ? 'Y' : 'N')); 315 DCHECK_CURRENTLY_ON(BrowserThread::UI);
316 DCHECK(remoter_);
317 VLOG(2) << __func__ << ": audio_stream_id = " << audio_stream_id
318 << " video_stream_id = " << video_stream_id;
319
320 if (!active_bridge_) {
321 remoter_->Stop(media::mojom::RemotingStopReason::SOURCE_GONE);
322 return;
323 }
324
325 if (audio_sender_request.is_pending() && audio_stream_id > -1) {
326 cast::CastRemotingSender::FindAndBind(
327 audio_stream_id, std::move(audio_pipe), std::move(audio_sender_request),
328 base::Bind(&CastRemotingConnector::OnDataSendFailed,
329 weak_factory_.GetWeakPtr()));
330 }
331 if (video_sender_request.is_pending() && video_stream_id > -1) {
332 cast::CastRemotingSender::FindAndBind(
333 video_stream_id, std::move(video_pipe), std::move(video_sender_request),
334 base::Bind(&CastRemotingConnector::OnDataSendFailed,
335 weak_factory_.GetWeakPtr()));
336 }
297 } 337 }
298 338
299 void CastRemotingConnector::StopRemoting(RemotingBridge* bridge, 339 void CastRemotingConnector::StopRemoting(RemotingBridge* bridge,
300 RemotingStopReason reason) { 340 RemotingStopReason reason) {
301 DCHECK_CURRENTLY_ON(BrowserThread::UI); 341 DCHECK_CURRENTLY_ON(BrowserThread::UI);
342 VLOG(2) << __func__ << ": reason = " << reason;
302 343
303 if (active_bridge_ != bridge) 344 if (active_bridge_ != bridge)
304 return; 345 return;
305 346
306 active_bridge_ = nullptr; 347 active_bridge_ = nullptr;
307 348
308 // Explicitly close the data pipes (and related requests) just in case the
309 // "start streams" operation was interrupted.
310 pending_audio_pipe_.reset();
311 pending_video_pipe_.reset();
312 pending_audio_sender_request_ = nullptr;
313 pending_video_sender_request_ = nullptr;
314
315 // Cancel all outstanding callbacks related to the remoting session. 349 // Cancel all outstanding callbacks related to the remoting session.
316 weak_factory_.InvalidateWeakPtrs(); 350 weak_factory_.InvalidateWeakPtrs();
317 351
318 // Prevent the source from trying to start again until the Cast Provider has 352 // Prevent the source from trying to start again until the Cast Provider has
319 // indicated the stop operation has completed. 353 // indicated the stop operation has completed.
320 bridge->OnSinkGone(); 354 bridge->OnSinkGone();
321 // Note: At this point, all sources should think the sink is gone. 355 // Note: At this point, all sources should think the sink is gone.
322 356
323 SendMessageToProvider(base::StringPrintf( 357 if (remoter_)
324 Messaging::kStopRemotingMessageFormat, session_counter_)); 358 remoter_->Stop(reason);
325 // Note: Once the Cast Provider sends back an acknowledgement message, all
326 // sources will be notified that the remoting sink is available again.
327 359
328 bridge->OnStopped(reason); 360 bridge->OnStopped(reason);
329 } 361 }
330 362
363 void CastRemotingConnector::OnStopped(RemotingStopReason reason) {
364 DCHECK_CURRENTLY_ON(BrowserThread::UI);
365 VLOG(2) << __func__ << ": reason = " << reason;
366
367 if (!active_bridge_)
368 return;
369 StopRemoting(active_bridge_, reason);
370 }
371
331 void CastRemotingConnector::SendMessageToSink( 372 void CastRemotingConnector::SendMessageToSink(
332 RemotingBridge* bridge, const std::vector<uint8_t>& message) { 373 RemotingBridge* bridge, const std::vector<uint8_t>& message) {
333 DCHECK_CURRENTLY_ON(BrowserThread::UI); 374 DCHECK_CURRENTLY_ON(BrowserThread::UI);
334 375
335 // During an active remoting session, simply pass all binary messages through 376 // During an active remoting session, simply pass all binary messages through
336 // to the sink. 377 // to the sink.
337 if (!message_observer_ || active_bridge_ != bridge) 378 if (!remoter_ || active_bridge_ != bridge)
338 return; 379 return;
339 media_router::MediaRoutesObserver::router()->SendRouteBinaryMessage( 380 remoter_->SendMessageToSink(message);
340 message_observer_->route_id(),
341 base::MakeUnique<std::vector<uint8_t>>(message),
342 base::Bind(&CastRemotingConnector::HandleSendMessageResult,
343 weak_factory_.GetWeakPtr()));
344 } 381 }
345 382
346 void CastRemotingConnector::SendMessageToProvider(const std::string& message) { 383 void CastRemotingConnector::OnMessageFromSink(
384 const std::vector<uint8_t>& message) {
347 DCHECK_CURRENTLY_ON(BrowserThread::UI); 385 DCHECK_CURRENTLY_ON(BrowserThread::UI);
348 386
349 if (!message_observer_) 387 // During an active remoting session, simply pass all binary messages through
388 // to the source.
389 if (!active_bridge_)
350 return; 390 return;
351 391 active_bridge_->OnMessageFromSink(message);
352 if (active_bridge_) {
353 media_router::MediaRoutesObserver::router()->SendRouteMessage(
354 message_observer_->route_id(), message,
355 base::Bind(&CastRemotingConnector::HandleSendMessageResult,
356 weak_factory_.GetWeakPtr()));
357 } else {
358 struct Helper {
359 static void IgnoreSendMessageResult(bool ignored) {}
360 };
361 media_router::MediaRoutesObserver::router()->SendRouteMessage(
362 message_observer_->route_id(), message,
363 base::Bind(&Helper::IgnoreSendMessageResult));
364 }
365 } 392 }
366 393
367 void CastRemotingConnector::ProcessMessagesFromRoute( 394 void CastRemotingConnector::OnSinkAvailable(
368 const std::vector<media_router::RouteMessage>& messages) { 395 media::mojom::SinkCapabilitiesPtr capabilities) {
369 DCHECK_CURRENTLY_ON(BrowserThread::UI); 396 DCHECK_CURRENTLY_ON(BrowserThread::UI);
397 VLOG(2) << __func__;
370 398
371 // Note: If any calls to message parsing functions are added/changed here, 399 // The receiver's capabilities are supposed unchanged during an active
imcheng 2017/07/05 18:53:08 s/are supposed/should be
xjz 2017/07/06 22:03:44 Done.
372 // please update cast_remoting_connector_fuzzertest.cc as well! 400 // remoting session.
401 if (active_bridge_) {
402 LOG(WARNING) << "Unexpected OnSinkAvailable() call during an active"
403 << "remoting session.";
404 return;
405 }
373 406
374 for (const media_router::RouteMessage& message : messages) { 407 // TODO(xjz): Pass the receiver's capabilities to the sources.
375 switch (message.type) { 408 for (RemotingBridge* notifyee : bridges_)
376 case media_router::RouteMessage::TEXT: 409 notifyee->OnSinkAvailable(enabled_features_);
377 // This is a notification message from the Cast Provider, about the
378 // execution state of the media remoting session between Chrome and the
379 // remote device.
380 DCHECK(message.text);
381
382 // If this is a "start streams" acknowledgement message, the
383 // CastRemotingSenders should now be available to begin consuming from
384 // the data pipes.
385 if (active_bridge_ &&
386 Messaging::IsMessageForSession(
387 *message.text,
388 Messaging::kStartedStreamsMessageFormatPartial,
389 session_counter_)) {
390 if (pending_audio_sender_request_.is_pending()) {
391 cast::CastRemotingSender::FindAndBind(
392 Messaging::GetStreamIdFromStartedMessage(
393 *message.text,
394 Messaging::kStartedStreamsMessageAudioIdSpecifier),
395 std::move(pending_audio_pipe_),
396 std::move(pending_audio_sender_request_),
397 base::Bind(&CastRemotingConnector::OnDataSendFailed,
398 weak_factory_.GetWeakPtr()));
399 }
400 if (pending_video_sender_request_.is_pending()) {
401 cast::CastRemotingSender::FindAndBind(
402 Messaging::GetStreamIdFromStartedMessage(
403 *message.text,
404 Messaging::kStartedStreamsMessageVideoIdSpecifier),
405 std::move(pending_video_pipe_),
406 std::move(pending_video_sender_request_),
407 base::Bind(&CastRemotingConnector::OnDataSendFailed,
408 weak_factory_.GetWeakPtr()));
409 }
410 break;
411 }
412
413 // If this is a failure message, call StopRemoting().
414 if (active_bridge_ &&
415 Messaging::IsMessageForSession(*message.text,
416 Messaging::kFailedMessageFormat,
417 session_counter_)) {
418 StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE);
419 break;
420 }
421
422 // If this is a stop acknowledgement message, indicating that the last
423 // session was stopped, notify all sources that the sink is once again
424 // available.
425 if (Messaging::IsMessageForSession(*message.text,
426 Messaging::kStoppedMessageFormat,
427 session_counter_)) {
428 if (active_bridge_) {
429 // Hmm...The Cast Provider was in a state that disagrees with this
430 // connector. Attempt to resolve this by shutting everything down to
431 // effectively reset to a known state.
432 LOG(WARNING) << "BUG: Cast Provider sent 'stopped' message during "
433 "an active remoting session.";
434 StopRemoting(active_bridge_,
435 RemotingStopReason::UNEXPECTED_FAILURE);
436 }
437 for (RemotingBridge* notifyee : bridges_)
438 notifyee->OnSinkAvailable(enabled_features_);
439 break;
440 }
441
442 LOG(WARNING) << "BUG: Unexpected message from Cast Provider: "
443 << *message.text;
444 break;
445
446 case media_router::RouteMessage::BINARY: // This is for the source.
447 DCHECK(message.binary);
448
449 // All binary messages are passed through to the source during an active
450 // remoting session.
451 if (active_bridge_)
452 active_bridge_->OnMessageFromSink(*message.binary);
453 break;
454 }
455 }
456 } 410 }
457 411
458 void CastRemotingConnector::HandleSendMessageResult(bool success) { 412 void CastRemotingConnector::OnError() {
459 DCHECK_CURRENTLY_ON(BrowserThread::UI); 413 DCHECK_CURRENTLY_ON(BrowserThread::UI);
460 // A single message send failure is treated as fatal to an active remoting 414 VLOG(2) << __func__;
461 // session. 415
462 if (!success && active_bridge_) 416 if (active_bridge_)
463 StopRemoting(active_bridge_, RemotingStopReason::MESSAGE_SEND_FAILED); 417 StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE);
464 } 418 }
465 419
466 void CastRemotingConnector::OnDataSendFailed() { 420 void CastRemotingConnector::OnDataSendFailed() {
467 DCHECK_CURRENTLY_ON(BrowserThread::UI); 421 DCHECK_CURRENTLY_ON(BrowserThread::UI);
422 VLOG(2) << __func__;
423
468 // A single data send failure is treated as fatal to an active remoting 424 // A single data send failure is treated as fatal to an active remoting
469 // session. 425 // session.
470 if (active_bridge_) 426 if (active_bridge_)
471 StopRemoting(active_bridge_, RemotingStopReason::DATA_SEND_FAILED); 427 StopRemoting(active_bridge_, RemotingStopReason::DATA_SEND_FAILED);
472 } 428 }
473
474 void CastRemotingConnector::OnRoutesUpdated(
475 const std::vector<media_router::MediaRoute>& routes,
476 const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) {
477 DCHECK_CURRENTLY_ON(BrowserThread::UI);
478
479 // If a remoting route has already been identified, check that it still
480 // exists. Otherwise, shut down messaging and any active remoting, and notify
481 // the sources that remoting is no longer available.
482 if (message_observer_) {
483 for (const media_router::MediaRoute& route : routes) {
484 if (message_observer_->route_id() == route.media_route_id())
485 return; // Remoting route still exists. Take no further action.
486 }
487 message_observer_.reset();
488 if (active_bridge_)
489 StopRemoting(active_bridge_, RemotingStopReason::ROUTE_TERMINATED);
490 for (RemotingBridge* notifyee : bridges_)
491 notifyee->OnSinkGone();
492 }
493
494 // There shouldn't be an active RemotingBridge at this point, since there is
495 // currently no known remoting route.
496 DCHECK(!active_bridge_);
497
498 // Scan |routes| for a new remoting route. If one is found, begin processing
499 // messages on the route, and notify the sources that remoting is now
500 // available.
501 for (const media_router::MediaRoute& route : routes) {
502 if (route.media_source().id() != media_source_id_)
503 continue;
504 message_observer_.reset(new MessageObserver(
505 media_router::MediaRoutesObserver::router(), route.media_route_id(),
506 this));
507 // TODO(miu): In the future, scan the route ID for sink capabilities
508 // properties and pass these to the source in the OnSinkAvailable()
509 // notification.
510 for (RemotingBridge* notifyee : bridges_)
511 notifyee->OnSinkAvailable(enabled_features_);
512 break;
513 }
514 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698