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

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

Powered by Google App Engine
This is Rietveld 408576698