| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/media/router/media_router_mojo_impl.h" | 5 #include "chrome/browser/media/router/media_router_mojo_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/guid.h" | 8 #include "base/guid.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_vector.h" |
| 11 #include "base/observer_list.h" | 11 #include "base/observer_list.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "chrome/browser/media/router/issues_observer.h" | 13 #include "chrome/browser/media/router/issues_observer.h" |
| 14 #include "chrome/browser/media/router/media_router_factory.h" | 14 #include "chrome/browser/media/router/media_router_factory.h" |
| 15 #include "chrome/browser/media/router/media_router_type_converters.h" | 15 #include "chrome/browser/media/router/media_router_type_converters.h" |
| 16 #include "chrome/browser/media/router/media_routes_observer.h" | 16 #include "chrome/browser/media/router/media_routes_observer.h" |
| 17 #include "chrome/browser/media/router/media_sinks_observer.h" | 17 #include "chrome/browser/media/router/media_sinks_observer.h" |
| 18 #include "chrome/browser/media/router/presentation_session_messages_observer.h" |
| 18 #include "extensions/browser/process_manager.h" | 19 #include "extensions/browser/process_manager.h" |
| 19 | 20 |
| 20 #define DVLOG_WITH_INSTANCE(level) \ | 21 #define DVLOG_WITH_INSTANCE(level) \ |
| 21 DVLOG(level) << "MR #" << instance_id_ << ": " | 22 DVLOG(level) << "MR #" << instance_id_ << ": " |
| 22 | 23 |
| 23 #define DLOG_WITH_INSTANCE(level) DLOG(level) << "MR #" << instance_id_ << ": " | 24 #define DLOG_WITH_INSTANCE(level) DLOG(level) << "MR #" << instance_id_ << ": " |
| 24 | 25 |
| 25 namespace media_router { | 26 namespace media_router { |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 28 // Converts the callback result of calling Mojo CreateRoute()/JoinRoute() | 29 // Converts the callback result of calling Mojo CreateRoute()/JoinRoute() |
| 29 // into a local callback. | 30 // into a local callback. |
| 30 void RouteResponseReceived( | 31 void RouteResponseReceived( |
| 32 const std::string& presentation_id, |
| 31 const std::vector<MediaRouteResponseCallback>& callbacks, | 33 const std::vector<MediaRouteResponseCallback>& callbacks, |
| 32 interfaces::MediaRoutePtr media_route, | 34 interfaces::MediaRoutePtr media_route, |
| 33 const mojo::String& error_text) { | 35 const mojo::String& error_text) { |
| 34 scoped_ptr<MediaRoute> route; | 36 scoped_ptr<MediaRoute> route; |
| 37 std::string actual_presentation_id; |
| 35 std::string error; | 38 std::string error; |
| 36 if (media_route.is_null()) { | 39 if (media_route.is_null()) { |
| 37 // An error occurred. | 40 // An error occurred. |
| 38 DCHECK(!error_text.is_null()); | 41 DCHECK(!error_text.is_null()); |
| 39 error = !error_text.get().empty() ? error_text.get() : "Unknown error."; | 42 error = !error_text.get().empty() ? error_text.get() : "Unknown error."; |
| 40 } else { | 43 } else { |
| 41 route = media_route.To<scoped_ptr<MediaRoute>>(); | 44 route = media_route.To<scoped_ptr<MediaRoute>>(); |
| 45 actual_presentation_id = presentation_id; |
| 42 } | 46 } |
| 43 | 47 |
| 44 for (const MediaRouteResponseCallback& callback : callbacks) | 48 for (const MediaRouteResponseCallback& callback : callbacks) |
| 45 callback.Run(route.get(), error); | 49 callback.Run(route.get(), actual_presentation_id, error); |
| 46 } | 50 } |
| 47 | 51 |
| 48 // TODO(imcheng): We should handle failure in this case. One way is to invoke | 52 // TODO(imcheng): We should handle failure in this case. One way is to invoke |
| 49 // all pending requests with failure. (crbug.com/490787) | 53 // all pending requests with failure. (crbug.com/490787) |
| 50 void EventPageWakeComplete(bool success) { | 54 void EventPageWakeComplete(bool success) { |
| 51 if (!success) | 55 if (!success) |
| 52 LOG(ERROR) << "An error encountered while waking the event page."; | 56 LOG(ERROR) << "An error encountered while waking the event page."; |
| 53 } | 57 } |
| 54 | 58 |
| 55 scoped_ptr<content::PresentationSessionMessage> | 59 scoped_ptr<content::PresentationSessionMessage> |
| 56 ConvertToPresentationSessionMessage(interfaces::RouteMessagePtr input) { | 60 ConvertToPresentationSessionMessage(interfaces::RouteMessagePtr input) { |
| 57 DCHECK(!input.is_null()); | 61 DCHECK(!input.is_null()); |
| 58 const auto& id_and_url = GetPresentationIdAndUrl(input->route_id); | |
| 59 const std::string& presentation_id = id_and_url.first; | |
| 60 const std::string& presentation_url = id_and_url.second; | |
| 61 scoped_ptr<content::PresentationSessionMessage> output; | 62 scoped_ptr<content::PresentationSessionMessage> output; |
| 62 switch (input->type) { | 63 switch (input->type) { |
| 63 case interfaces::RouteMessage::Type::TYPE_TEXT: { | 64 case interfaces::RouteMessage::Type::TYPE_TEXT: { |
| 64 DCHECK(!input->message.is_null()); | 65 DCHECK(!input->message.is_null()); |
| 65 DCHECK(input->data.is_null()); | 66 DCHECK(input->data.is_null()); |
| 66 output = content::PresentationSessionMessage::CreateStringMessage( | 67 output.reset(new content::PresentationSessionMessage( |
| 67 presentation_url, presentation_id, make_scoped_ptr(new std::string)); | 68 content::PresentationMessageType::TEXT)); |
| 68 input->message.Swap(output->message.get()); | 69 input->message.Swap(&output->message); |
| 69 return output.Pass(); | 70 return output.Pass(); |
| 70 } | 71 } |
| 71 case interfaces::RouteMessage::Type::TYPE_BINARY: { | 72 case interfaces::RouteMessage::Type::TYPE_BINARY: { |
| 72 DCHECK(!input->data.is_null()); | 73 DCHECK(!input->data.is_null()); |
| 73 DCHECK(input->message.is_null()); | 74 DCHECK(input->message.is_null()); |
| 74 output = content::PresentationSessionMessage::CreateArrayBufferMessage( | 75 output.reset(new content::PresentationSessionMessage( |
| 75 presentation_url, presentation_id, | 76 content::PresentationMessageType::ARRAY_BUFFER)); |
| 76 make_scoped_ptr(new std::vector<uint8_t>)); | 77 output->data.reset(new std::vector<uint8_t>); |
| 77 input->data.Swap(output->data.get()); | 78 input->data.Swap(output->data.get()); |
| 78 return output.Pass(); | 79 return output.Pass(); |
| 79 } | 80 } |
| 80 } | 81 } |
| 81 | 82 |
| 82 NOTREACHED() << "Invalid route message type " << input->type; | 83 NOTREACHED() << "Invalid route message type " << input->type; |
| 83 return output.Pass(); | 84 return output.Pass(); |
| 84 } | 85 } |
| 85 | 86 |
| 86 } // namespace | 87 } // namespace |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 const MediaSource::Id& source_id, | 195 const MediaSource::Id& source_id, |
| 195 const MediaSink::Id& sink_id, | 196 const MediaSink::Id& sink_id, |
| 196 const GURL& origin, | 197 const GURL& origin, |
| 197 int tab_id, | 198 int tab_id, |
| 198 const std::vector<MediaRouteResponseCallback>& callbacks) { | 199 const std::vector<MediaRouteResponseCallback>& callbacks) { |
| 199 DCHECK(thread_checker_.CalledOnValidThread()); | 200 DCHECK(thread_checker_.CalledOnValidThread()); |
| 200 | 201 |
| 201 if (!origin.is_valid()) { | 202 if (!origin.is_valid()) { |
| 202 DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; | 203 DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; |
| 203 for (const MediaRouteResponseCallback& callback : callbacks) | 204 for (const MediaRouteResponseCallback& callback : callbacks) |
| 204 callback.Run(nullptr, "Invalid origin"); | 205 callback.Run(nullptr, "", "Invalid origin"); |
| 205 return; | 206 return; |
| 206 } | 207 } |
| 207 RunOrDefer(base::Bind( | 208 RunOrDefer(base::Bind( |
| 208 &MediaRouterMojoImpl::DoCreateRoute, base::Unretained(this), source_id, | 209 &MediaRouterMojoImpl::DoCreateRoute, base::Unretained(this), source_id, |
| 209 sink_id, origin.is_empty() ? "" : origin.spec(), tab_id, callbacks)); | 210 sink_id, origin.is_empty() ? "" : origin.spec(), tab_id, callbacks)); |
| 210 } | 211 } |
| 211 | 212 |
| 212 void MediaRouterMojoImpl::JoinRoute( | 213 void MediaRouterMojoImpl::JoinRoute( |
| 213 const MediaSource::Id& source_id, | 214 const MediaSource::Id& source_id, |
| 214 const std::string& presentation_id, | 215 const std::string& presentation_id, |
| 215 const GURL& origin, | 216 const GURL& origin, |
| 216 int tab_id, | 217 int tab_id, |
| 217 const std::vector<MediaRouteResponseCallback>& callbacks) { | 218 const std::vector<MediaRouteResponseCallback>& callbacks) { |
| 218 DCHECK(thread_checker_.CalledOnValidThread()); | 219 DCHECK(thread_checker_.CalledOnValidThread()); |
| 219 | 220 |
| 220 if (!origin.is_valid()) { | 221 if (!origin.is_valid()) { |
| 221 DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; | 222 DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; |
| 222 for (const MediaRouteResponseCallback& callback : callbacks) | 223 for (const MediaRouteResponseCallback& callback : callbacks) |
| 223 callback.Run(nullptr, "Invalid origin"); | 224 callback.Run(nullptr, "", "Invalid origin"); |
| 224 return; | 225 return; |
| 225 } | 226 } |
| 226 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoJoinRoute, | 227 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoJoinRoute, |
| 227 base::Unretained(this), source_id, presentation_id, | 228 base::Unretained(this), source_id, presentation_id, |
| 228 origin.is_empty() ? "" : origin.spec(), tab_id, | 229 origin.is_empty() ? "" : origin.spec(), tab_id, |
| 229 callbacks)); | 230 callbacks)); |
| 230 } | 231 } |
| 231 | 232 |
| 232 void MediaRouterMojoImpl::CloseRoute(const MediaRoute::Id& route_id) { | 233 void MediaRouterMojoImpl::CloseRoute(const MediaRoute::Id& route_id) { |
| 233 DCHECK(thread_checker_.CalledOnValidThread()); | 234 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 250 const MediaRoute::Id& route_id, | 251 const MediaRoute::Id& route_id, |
| 251 scoped_ptr<std::vector<uint8>> data, | 252 scoped_ptr<std::vector<uint8>> data, |
| 252 const SendRouteMessageCallback& callback) { | 253 const SendRouteMessageCallback& callback) { |
| 253 DCHECK(thread_checker_.CalledOnValidThread()); | 254 DCHECK(thread_checker_.CalledOnValidThread()); |
| 254 | 255 |
| 255 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoSendSessionBinaryMessage, | 256 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoSendSessionBinaryMessage, |
| 256 base::Unretained(this), route_id, | 257 base::Unretained(this), route_id, |
| 257 base::Passed(data.Pass()), callback)); | 258 base::Passed(data.Pass()), callback)); |
| 258 } | 259 } |
| 259 | 260 |
| 260 void MediaRouterMojoImpl::ListenForRouteMessages( | |
| 261 const std::vector<MediaRoute::Id>& route_ids, | |
| 262 const PresentationSessionMessageCallback& message_cb) { | |
| 263 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 264 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoListenForRouteMessages, | |
| 265 base::Unretained(this), route_ids, message_cb)); | |
| 266 } | |
| 267 | |
| 268 void MediaRouterMojoImpl::ClearIssue(const Issue::Id& issue_id) { | 261 void MediaRouterMojoImpl::ClearIssue(const Issue::Id& issue_id) { |
| 269 DCHECK(thread_checker_.CalledOnValidThread()); | 262 DCHECK(thread_checker_.CalledOnValidThread()); |
| 270 issue_manager_.ClearIssue(issue_id); | 263 issue_manager_.ClearIssue(issue_id); |
| 271 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoClearIssue, | 264 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoClearIssue, |
| 272 base::Unretained(this), issue_id)); | 265 base::Unretained(this), issue_id)); |
| 273 } | 266 } |
| 274 | 267 |
| 275 void MediaRouterMojoImpl::RegisterMediaSinksObserver( | 268 void MediaRouterMojoImpl::RegisterMediaSinksObserver( |
| 276 MediaSinksObserver* observer) { | 269 MediaSinksObserver* observer) { |
| 277 DCHECK(thread_checker_.CalledOnValidThread()); | 270 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 293 // TODO(imcheng): Implement caching. (crbug.com/492451) | 286 // TODO(imcheng): Implement caching. (crbug.com/492451) |
| 294 observer_list->AddObserver(observer); | 287 observer_list->AddObserver(observer); |
| 295 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStartObservingMediaSinks, | 288 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStartObservingMediaSinks, |
| 296 base::Unretained(this), source_id)); | 289 base::Unretained(this), source_id)); |
| 297 } | 290 } |
| 298 | 291 |
| 299 void MediaRouterMojoImpl::UnregisterMediaSinksObserver( | 292 void MediaRouterMojoImpl::UnregisterMediaSinksObserver( |
| 300 MediaSinksObserver* observer) { | 293 MediaSinksObserver* observer) { |
| 301 DCHECK(thread_checker_.CalledOnValidThread()); | 294 DCHECK(thread_checker_.CalledOnValidThread()); |
| 302 | 295 |
| 303 const std::string& source_id = observer->source().id(); | 296 const MediaSource::Id& source_id = observer->source().id(); |
| 304 auto* observer_list = sinks_observers_.get(source_id); | 297 auto* observer_list = sinks_observers_.get(source_id); |
| 305 if (!observer_list || !observer_list->HasObserver(observer)) { | 298 if (!observer_list || !observer_list->HasObserver(observer)) { |
| 306 return; | 299 return; |
| 307 } | 300 } |
| 308 | 301 |
| 309 // If we are removing the final observer for the source, then stop | 302 // If we are removing the final observer for the source, then stop |
| 310 // observing sinks for it. | 303 // observing sinks for it. |
| 311 // might_have_observers() is reliable here on the assumption that this call | 304 // might_have_observers() is reliable here on the assumption that this call |
| 312 // is not inside the ObserverList iteration. | 305 // is not inside the ObserverList iteration. |
| 313 observer_list->RemoveObserver(observer); | 306 observer_list->RemoveObserver(observer); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 343 void MediaRouterMojoImpl::RegisterIssuesObserver(IssuesObserver* observer) { | 336 void MediaRouterMojoImpl::RegisterIssuesObserver(IssuesObserver* observer) { |
| 344 DCHECK(thread_checker_.CalledOnValidThread()); | 337 DCHECK(thread_checker_.CalledOnValidThread()); |
| 345 issue_manager_.RegisterObserver(observer); | 338 issue_manager_.RegisterObserver(observer); |
| 346 } | 339 } |
| 347 | 340 |
| 348 void MediaRouterMojoImpl::UnregisterIssuesObserver(IssuesObserver* observer) { | 341 void MediaRouterMojoImpl::UnregisterIssuesObserver(IssuesObserver* observer) { |
| 349 DCHECK(thread_checker_.CalledOnValidThread()); | 342 DCHECK(thread_checker_.CalledOnValidThread()); |
| 350 issue_manager_.UnregisterObserver(observer); | 343 issue_manager_.UnregisterObserver(observer); |
| 351 } | 344 } |
| 352 | 345 |
| 346 void MediaRouterMojoImpl::RegisterPresentationSessionMessagesObserver( |
| 347 PresentationSessionMessagesObserver* observer) { |
| 348 DCHECK(thread_checker_.CalledOnValidThread()); |
| 349 DCHECK(observer); |
| 350 const MediaRoute::Id& route_id = observer->route_id(); |
| 351 auto* observer_list = messages_observers_.get(route_id); |
| 352 if (!observer_list) { |
| 353 observer_list = new base::ObserverList<PresentationSessionMessagesObserver>; |
| 354 messages_observers_.add(route_id, make_scoped_ptr(observer_list)); |
| 355 } else { |
| 356 DCHECK(!observer_list->HasObserver(observer)); |
| 357 } |
| 358 |
| 359 bool should_listen = !observer_list->might_have_observers(); |
| 360 observer_list->AddObserver(observer); |
| 361 if (should_listen) { |
| 362 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoListenForRouteMessages, |
| 363 base::Unretained(this), route_id)); |
| 364 } |
| 365 } |
| 366 |
| 367 void MediaRouterMojoImpl::UnregisterPresentationSessionMessagesObserver( |
| 368 PresentationSessionMessagesObserver* observer) { |
| 369 DCHECK(thread_checker_.CalledOnValidThread()); |
| 370 DCHECK(observer); |
| 371 |
| 372 const MediaRoute::Id& route_id = observer->route_id(); |
| 373 auto* observer_list = messages_observers_.get(route_id); |
| 374 if (!observer_list || !observer_list->HasObserver(observer)) |
| 375 return; |
| 376 |
| 377 observer_list->RemoveObserver(observer); |
| 378 if (!observer_list->might_have_observers()) |
| 379 messages_observers_.erase(route_id); |
| 380 // TODO(imcheng): Queue a task to stop listening for messages by asking |
| 381 // the extension to invoke the oustanding Mojo callback with empty list. We |
| 382 // don't want the Mojo callback to exist indefinitely on the extension side |
| 383 // and there is currently no way to cancel the callback from this side. |
| 384 } |
| 385 |
| 353 void MediaRouterMojoImpl::DoCreateRoute( | 386 void MediaRouterMojoImpl::DoCreateRoute( |
| 354 const MediaSource::Id& source_id, | 387 const MediaSource::Id& source_id, |
| 355 const MediaSink::Id& sink_id, | 388 const MediaSink::Id& sink_id, |
| 356 const std::string& origin, | 389 const std::string& origin, |
| 357 int tab_id, | 390 int tab_id, |
| 358 const std::vector<MediaRouteResponseCallback>& callbacks) { | 391 const std::vector<MediaRouteResponseCallback>& callbacks) { |
| 359 std::string presentation_id("mr_"); | 392 std::string presentation_id("mr_"); |
| 360 presentation_id += base::GenerateGUID(); | 393 presentation_id += base::GenerateGUID(); |
| 361 DVLOG_WITH_INSTANCE(1) << "DoCreateRoute " << source_id << "=>" << sink_id | 394 DVLOG_WITH_INSTANCE(1) << "DoCreateRoute " << source_id << "=>" << sink_id |
| 362 << ", presentation ID: " << presentation_id; | 395 << ", presentation ID: " << presentation_id; |
| 363 media_route_provider_->CreateRoute( | 396 media_route_provider_->CreateRoute( |
| 364 source_id, sink_id, presentation_id, origin, tab_id, | 397 source_id, sink_id, presentation_id, origin, tab_id, |
| 365 base::Bind(&RouteResponseReceived, callbacks)); | 398 base::Bind(&RouteResponseReceived, presentation_id, callbacks)); |
| 366 } | 399 } |
| 367 | 400 |
| 368 void MediaRouterMojoImpl::DoJoinRoute( | 401 void MediaRouterMojoImpl::DoJoinRoute( |
| 369 const MediaSource::Id& source_id, | 402 const MediaSource::Id& source_id, |
| 370 const std::string& presentation_id, | 403 const std::string& presentation_id, |
| 371 const std::string& origin, | 404 const std::string& origin, |
| 372 int tab_id, | 405 int tab_id, |
| 373 const std::vector<MediaRouteResponseCallback>& callbacks) { | 406 const std::vector<MediaRouteResponseCallback>& callbacks) { |
| 374 DVLOG_WITH_INSTANCE(1) << "DoJoinRoute " << source_id | 407 DVLOG_WITH_INSTANCE(1) << "DoJoinRoute " << source_id |
| 375 << ", presentation ID: " << presentation_id; | 408 << ", presentation ID: " << presentation_id; |
| 376 media_route_provider_->JoinRoute( | 409 media_route_provider_->JoinRoute( |
| 377 source_id, presentation_id, origin, tab_id, | 410 source_id, presentation_id, origin, tab_id, |
| 378 base::Bind(&RouteResponseReceived, callbacks)); | 411 base::Bind(&RouteResponseReceived, presentation_id, callbacks)); |
| 379 } | 412 } |
| 380 | 413 |
| 381 void MediaRouterMojoImpl::DoCloseRoute(const MediaRoute::Id& route_id) { | 414 void MediaRouterMojoImpl::DoCloseRoute(const MediaRoute::Id& route_id) { |
| 382 DVLOG_WITH_INSTANCE(1) << "DoCloseRoute " << route_id; | 415 DVLOG_WITH_INSTANCE(1) << "DoCloseRoute " << route_id; |
| 383 media_route_provider_->CloseRoute(route_id); | 416 media_route_provider_->CloseRoute(route_id); |
| 384 } | 417 } |
| 385 | 418 |
| 386 void MediaRouterMojoImpl::DoSendSessionMessage( | 419 void MediaRouterMojoImpl::DoSendSessionMessage( |
| 387 const MediaRoute::Id& route_id, | 420 const MediaRoute::Id& route_id, |
| 388 const std::string& message, | 421 const std::string& message, |
| 389 const SendRouteMessageCallback& callback) { | 422 const SendRouteMessageCallback& callback) { |
| 390 DVLOG_WITH_INSTANCE(1) << "SendRouteMessage " << route_id; | 423 DVLOG_WITH_INSTANCE(1) << "SendRouteMessage " << route_id; |
| 391 media_route_provider_->SendRouteMessage(route_id, message, callback); | 424 media_route_provider_->SendRouteMessage(route_id, message, callback); |
| 392 } | 425 } |
| 393 | 426 |
| 394 void MediaRouterMojoImpl::DoSendSessionBinaryMessage( | 427 void MediaRouterMojoImpl::DoSendSessionBinaryMessage( |
| 395 const MediaRoute::Id& route_id, | 428 const MediaRoute::Id& route_id, |
| 396 scoped_ptr<std::vector<uint8>> data, | 429 scoped_ptr<std::vector<uint8>> data, |
| 397 const SendRouteMessageCallback& callback) { | 430 const SendRouteMessageCallback& callback) { |
| 398 DVLOG_WITH_INSTANCE(1) << "SendRouteBinaryMessage " << route_id; | 431 DVLOG_WITH_INSTANCE(1) << "SendRouteBinaryMessage " << route_id; |
| 399 mojo::Array<uint8> mojo_array; | 432 mojo::Array<uint8> mojo_array; |
| 400 mojo_array.Swap(data.get()); | 433 mojo_array.Swap(data.get()); |
| 401 media_route_provider_->SendRouteBinaryMessage(route_id, mojo_array.Pass(), | 434 media_route_provider_->SendRouteBinaryMessage(route_id, mojo_array.Pass(), |
| 402 callback); | 435 callback); |
| 403 } | 436 } |
| 404 | 437 |
| 405 void MediaRouterMojoImpl::DoListenForRouteMessages( | 438 void MediaRouterMojoImpl::DoListenForRouteMessages( |
| 406 const std::vector<MediaRoute::Id>& route_ids, | 439 const MediaRoute::Id& route_id) { |
| 407 const PresentationSessionMessageCallback& message_cb) { | |
| 408 DVLOG_WITH_INSTANCE(1) << "ListenForRouteMessages"; | 440 DVLOG_WITH_INSTANCE(1) << "ListenForRouteMessages"; |
| 409 media_route_provider_->ListenForRouteMessages( | 441 if (!ContainsValue(route_ids_listening_for_messages_, route_id)) { |
| 410 mojo::Array<mojo::String>::From(route_ids), | 442 route_ids_listening_for_messages_.insert(route_id); |
| 411 base::Bind(&MediaRouterMojoImpl::OnRouteMessageReceived, | 443 media_route_provider_->ListenForRouteMessages( |
| 412 base::Unretained(this), message_cb)); | 444 route_id, base::Bind(&MediaRouterMojoImpl::OnRouteMessagesReceived, |
| 445 base::Unretained(this), route_id)); |
| 446 } |
| 413 } | 447 } |
| 414 | 448 |
| 415 void MediaRouterMojoImpl::OnRouteMessageReceived( | 449 void MediaRouterMojoImpl::OnRouteMessagesReceived( |
| 416 const PresentationSessionMessageCallback& message_cb, | 450 const MediaRoute::Id& route_id, |
| 417 mojo::Array<interfaces::RouteMessagePtr> messages) { | 451 mojo::Array<interfaces::RouteMessagePtr> messages) { |
| 418 scoped_ptr<ScopedVector<content::PresentationSessionMessage>> | 452 DVLOG(1) << "OnRouteMessagesReceived"; |
| 419 session_messages(new ScopedVector<content::PresentationSessionMessage>()); | 453 |
| 420 for (size_t i = 0; i < messages.size(); ++i) { | 454 // Check if there are any observers remaining. If not, the messages |
| 421 session_messages->push_back( | 455 // can be discarded and we can stop listening for the next batch of messages. |
| 422 ConvertToPresentationSessionMessage(messages[i].Pass()).Pass()); | 456 auto* observer_list = messages_observers_.get(route_id); |
| 457 if (!observer_list) { |
| 458 route_ids_listening_for_messages_.erase(route_id); |
| 459 return; |
| 423 } | 460 } |
| 424 message_cb.Run(session_messages.Pass()); | 461 |
| 462 // Empty |messages| means we told the extension that we were no longer |
| 463 // listening for messages on that route. But since now we have observers |
| 464 // again, we should keep listening. |
| 465 if (messages.storage().empty()) { |
| 466 DVLOG(2) << "Received empty messages for " << route_id; |
| 467 } else { |
| 468 ScopedVector<content::PresentationSessionMessage> session_messages; |
| 469 session_messages.reserve(messages.size()); |
| 470 for (size_t i = 0; i < messages.size(); ++i) { |
| 471 session_messages.push_back( |
| 472 ConvertToPresentationSessionMessage(messages[i].Pass()).Pass()); |
| 473 } |
| 474 |
| 475 // TODO(imcheng): If there is only 1 observer, we should be able to pass |
| 476 // the messages to avoid additional copies. (crbug.com/517234) |
| 477 FOR_EACH_OBSERVER(PresentationSessionMessagesObserver, *observer_list, |
| 478 OnMessagesReceived(session_messages)); |
| 479 } |
| 480 |
| 481 // Listen for more messages. |
| 482 media_route_provider_->ListenForRouteMessages( |
| 483 route_id, base::Bind(&MediaRouterMojoImpl::OnRouteMessagesReceived, |
| 484 base::Unretained(this), route_id)); |
| 425 } | 485 } |
| 426 | 486 |
| 427 void MediaRouterMojoImpl::DoClearIssue(const Issue::Id& issue_id) { | 487 void MediaRouterMojoImpl::DoClearIssue(const Issue::Id& issue_id) { |
| 428 DVLOG_WITH_INSTANCE(1) << "DoClearIssue " << issue_id; | 488 DVLOG_WITH_INSTANCE(1) << "DoClearIssue " << issue_id; |
| 429 media_route_provider_->ClearIssue(issue_id); | 489 media_route_provider_->ClearIssue(issue_id); |
| 430 } | 490 } |
| 431 | 491 |
| 432 void MediaRouterMojoImpl::DoStartObservingMediaSinks( | 492 void MediaRouterMojoImpl::DoStartObservingMediaSinks( |
| 433 const MediaSource::Id& source_id) { | 493 const MediaSource::Id& source_id) { |
| 434 DVLOG_WITH_INSTANCE(1) << "DoStartObservingMediaSinks: " << source_id; | 494 DVLOG_WITH_INSTANCE(1) << "DoStartObservingMediaSinks: " << source_id; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 return; | 555 return; |
| 496 } | 556 } |
| 497 | 557 |
| 498 for (const auto& next_request : pending_requests_) | 558 for (const auto& next_request : pending_requests_) |
| 499 next_request.Run(); | 559 next_request.Run(); |
| 500 | 560 |
| 501 pending_requests_.clear(); | 561 pending_requests_.clear(); |
| 502 } | 562 } |
| 503 | 563 |
| 504 } // namespace media_router | 564 } // namespace media_router |
| OLD | NEW |