Chromium Code Reviews| Index: chrome/browser/media/router/media_router_mojo_impl.cc |
| diff --git a/chrome/browser/media/router/media_router_mojo_impl.cc b/chrome/browser/media/router/media_router_mojo_impl.cc |
| index ab4249eb9c3f73eae96de1a4854df222f74f11fe..fc89f58a16d7239abba923b3e0ece3281dec3c43 100644 |
| --- a/chrome/browser/media/router/media_router_mojo_impl.cc |
| +++ b/chrome/browser/media/router/media_router_mojo_impl.cc |
| @@ -74,12 +74,17 @@ MediaRouterMojoImpl::MediaRouterMediaRoutesObserver:: |
| ~MediaRouterMediaRoutesObserver() { |
| } |
| +MediaRouterMojoImpl::MediaRoutesQuery::MediaRoutesQuery() = default; |
| + |
| +MediaRouterMojoImpl::MediaRoutesQuery::~MediaRoutesQuery() = default; |
| + |
| MediaRouterMojoImpl::MediaSinksQuery::MediaSinksQuery() = default; |
| MediaRouterMojoImpl::MediaSinksQuery::~MediaSinksQuery() = default; |
| void MediaRouterMojoImpl::MediaRouterMediaRoutesObserver::OnRoutesUpdated( |
| - const std::vector<media_router::MediaRoute>& routes) { |
| + const std::vector<media_router::MediaRoute>& routes, |
| + const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) { |
| bool has_local_display_route = |
| std::find_if(routes.begin(), routes.end(), |
| [](const media_router::MediaRoute& route) { |
| @@ -192,6 +197,14 @@ void MediaRouterMojoImpl::OnSinksReceived( |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DVLOG_WITH_INSTANCE(1) << "OnSinksReceived"; |
| + auto it = sinks_queries_.find(media_source); |
| + if (it == sinks_queries_.end() || |
| + !(it->second->observers.might_have_observers())) { |
| + DVLOG_WITH_INSTANCE(1) |
| + << "Received sink list without any active observers: " << media_source; |
| + return; |
| + } |
| + |
| std::vector<MediaSink> sinks_converted; |
| sinks_converted.reserve(sinks.size()); |
| @@ -199,32 +212,40 @@ void MediaRouterMojoImpl::OnSinksReceived( |
| sinks_converted.push_back(sinks[i].To<MediaSink>()); |
| } |
| - auto it = sinks_queries_.find(media_source); |
| - if (it == sinks_queries_.end() || |
| - !(it->second->observers.might_have_observers())) { |
| - DVLOG_WITH_INSTANCE(1) |
| - << "Received sink list without any active observers: " << media_source; |
| - } else { |
| - FOR_EACH_OBSERVER(MediaSinksObserver, it->second->observers, |
| - OnSinksReceived(sinks_converted)); |
| - } |
| + FOR_EACH_OBSERVER(MediaSinksObserver, it->second->observers, |
| + OnSinksReceived(sinks_converted)); |
| } |
| void MediaRouterMojoImpl::OnRoutesUpdated( |
| - mojo::Array<interfaces::MediaRoutePtr> routes) { |
| + const mojo::String& media_source, |
| + mojo::Array<interfaces::MediaRoutePtr> routes, |
| + mojo::Array<mojo::String> joinable_route_ids) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DVLOG_WITH_INSTANCE(1) << "OnRoutesUpdated"; |
| + auto it = routes_queries_.find(media_source); |
| + if (it == routes_queries_.end() || |
| + !(it->second->observers.might_have_observers())) { |
| + DVLOG_WITH_INSTANCE(1) |
| + << "Received route list without any active observers: " << media_source; |
| + return; |
| + } |
| std::vector<MediaRoute> routes_converted; |
| routes_converted.reserve(routes.size()); |
| - for (size_t i = 0; i < routes.size(); ++i) { |
| + std::vector<MediaRoute::Id> joinable_routes_converted; |
| + joinable_routes_converted.reserve(joinable_route_ids.size()); |
| + |
| + for (size_t i = 0; i < routes.size(); ++i) |
| routes_converted.push_back(routes[i].To<MediaRoute>()); |
| - } |
| - FOR_EACH_OBSERVER(MediaRoutesObserver, routes_observers_, |
| - OnRoutesUpdated(routes_converted)); |
| + for (size_t i = 0; i < joinable_route_ids.size(); ++i) |
| + joinable_routes_converted.push_back(joinable_route_ids[i]); |
| + |
| + FOR_EACH_OBSERVER(MediaRoutesObserver, it->second->observers, |
| + OnRoutesUpdated(routes_converted, |
| + joinable_routes_converted)); |
| } |
| void MediaRouterMojoImpl::RouteResponseReceived( |
| @@ -314,6 +335,30 @@ void MediaRouterMojoImpl::JoinRoute( |
| callbacks)); |
| } |
| +void MediaRouterMojoImpl::JoinRouteByRouteId( |
| + const MediaSource::Id& source_id, |
| + const MediaRoute::Id& route_id, |
| + const GURL& origin, |
| + content::WebContents* web_contents, |
| + const std::vector<MediaRouteResponseCallback>& callbacks) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (!origin.is_valid()) { |
| + DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; |
| + for (const MediaRouteResponseCallback& callback : callbacks) |
| + callback.Run(nullptr, "", "Invalid origin"); |
| + return; |
| + } |
| + |
| + int tab_id = SessionTabHelper::IdForTab(web_contents); |
| + std::string presentation_id("non-local-join_"); |
|
mark a. foltz
2015/12/03 19:24:23
What is this for - shouldn't the route_id already
matt.boetger
2015/12/15 19:21:20
Since this is non-local, the route_id contains the
|
| + presentation_id += route_id; |
| + RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoJoinRoute, |
|
mark a. foltz
2015/12/03 19:24:23
I'm not sure DoJoinRoute is the right API to call
matt.boetger
2015/12/15 19:21:20
Yes, the fake presentation id was a way to re-use
|
| + base::Unretained(this), source_id, presentation_id, |
| + origin.is_empty() ? "" : origin.spec(), tab_id, |
| + callbacks)); |
| +} |
| + |
| void MediaRouterMojoImpl::CloseRoute(const MediaRoute::Id& route_id) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| @@ -430,24 +475,38 @@ void MediaRouterMojoImpl::UnregisterMediaSinksObserver( |
| void MediaRouterMojoImpl::RegisterMediaRoutesObserver( |
| MediaRoutesObserver* observer) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - DCHECK(!routes_observers_.HasObserver(observer)); |
| + const MediaSource::Id source_id = observer->source_id(); |
| + auto* routes_query = routes_queries_.get(source_id); |
| + if (!routes_query) { |
| + routes_query = new MediaRoutesQuery; |
| + routes_queries_.add(source_id, make_scoped_ptr(routes_query)); |
| + } else { |
| + DCHECK(!routes_query->observers.HasObserver(observer)); |
| + } |
| + routes_query->observers.AddObserver(observer); |
| SetWakeReason(MediaRouteProviderWakeReason::START_OBSERVING_MEDIA_ROUTES); |
| RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStartObservingMediaRoutes, |
| - base::Unretained(this))); |
| - routes_observers_.AddObserver(observer); |
| + base::Unretained(this), source_id)); |
| } |
| void MediaRouterMojoImpl::UnregisterMediaRoutesObserver( |
| MediaRoutesObserver* observer) { |
| - if (!routes_observers_.HasObserver(observer)) |
| + const MediaSource::Id source_id = observer->source_id(); |
| + auto* routes_query = routes_queries_.get(source_id); |
| + if (!routes_query || !routes_query->observers.HasObserver(observer)) { |
| return; |
| + } |
| - routes_observers_.RemoveObserver(observer); |
| - if (!routes_observers_.might_have_observers()) { |
| + // If we are removing the final observer for the source, then stop |
| + // observing routes for it. |
| + // might_have_observers() is reliable here on the assumption that this call |
| + // is not inside the ObserverList iteration. |
| + routes_query->observers.RemoveObserver(observer); |
| + if (!routes_query->observers.might_have_observers()) { |
| SetWakeReason(MediaRouteProviderWakeReason::STOP_OBSERVING_MEDIA_ROUTES); |
| RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStopObservingMediaRoutes, |
| - base::Unretained(this))); |
| + base::Unretained(this), source_id)); |
| } |
| } |
| @@ -724,14 +783,36 @@ void MediaRouterMojoImpl::DoStopObservingMediaSinks( |
| sinks_queries_.erase(source_id); |
| } |
| -void MediaRouterMojoImpl::DoStartObservingMediaRoutes() { |
| +void MediaRouterMojoImpl::DoStartObservingMediaRoutes( |
| + const MediaSource::Id& source_id) { |
| DVLOG_WITH_INSTANCE(1) << "DoStartObservingMediaRoutes"; |
| - media_route_provider_->StartObservingMediaRoutes(); |
| + |
| + // No need to call MRPM if all observers have been removed in the meantime. |
| + auto* routes_query = routes_queries_.get(source_id); |
|
mark a. foltz
2015/12/03 19:24:23
This pattern is repeated a couple of times - pleas
matt.boetger
2015/12/15 19:21:20
Done.
|
| + if (!routes_query || !routes_query->observers.might_have_observers()) { |
| + return; |
| + } |
| + |
| + DVLOG_WITH_INSTANCE(1) << "MRPM.StartObservingMediaRoutes: " << source_id; |
| + media_route_provider_->StartObservingMediaRoutes(source_id); |
| + routes_query->is_active = true; |
| } |
| -void MediaRouterMojoImpl::DoStopObservingMediaRoutes() { |
| +void MediaRouterMojoImpl::DoStopObservingMediaRoutes( |
| + const MediaSource::Id& source_id) { |
| DVLOG_WITH_INSTANCE(1) << "DoStopObservingMediaRoutes"; |
| - media_route_provider_->StopObservingMediaRoutes(); |
| + |
| + auto* routes_query = routes_queries_.get(source_id); |
| + // No need to call MRPM if observers have been added in the meantime, |
| + // or StopObservingMediaSinks has already been called. |
| + if (!routes_query || !routes_query->is_active || |
| + routes_query->observers.might_have_observers()) { |
| + return; |
| + } |
| + |
| + DVLOG_WITH_INSTANCE(1) << "MRPM.StopObservingMediaRoutes: " << source_id; |
| + media_route_provider_->StopObservingMediaRoutes(source_id); |
| + routes_queries_.erase(source_id); |
| } |
| void MediaRouterMojoImpl::EnqueueTask(const base::Closure& closure) { |