Chromium Code Reviews| Index: chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc |
| diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc |
| index 1ad648bc2b645d98e5b9983a68b5b54c95ebff3f..3b1e3f993a94bcd7c40126de0ca516e5c3134ebe 100644 |
| --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc |
| +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc |
| @@ -28,8 +28,6 @@ enum ErrorType { |
| }; |
| ErrorType CreateCastMediaSink(const media_router::DnsSdService& service, |
| - int channel_id, |
| - bool audio_only, |
| media_router::MediaSinkInternal* cast_sink) { |
| DCHECK(cast_sink); |
| if (service.service_name.find( |
| @@ -41,6 +39,10 @@ ErrorType CreateCastMediaSink(const media_router::DnsSdService& service, |
| if (!ip_address.AssignFromIPLiteral(service.ip_address)) |
| return ErrorType::MISSING_OR_INVALID_IP_ADDRESS; |
| + net::HostPortPair host_port_pair = |
| + net::HostPortPair::FromString(service.service_host_port); |
| + int port = host_port_pair.port(); |
| + |
| std::map<std::string, std::string> service_data; |
| for (const auto& item : service.service_data) { |
| // |item| format should be "id=xxxxxx", etc. |
| @@ -69,10 +71,8 @@ ErrorType CreateCastMediaSink(const media_router::DnsSdService& service, |
| media_router::CastSinkExtraData extra_data; |
| extra_data.ip_address = ip_address; |
| extra_data.model_name = service_data["md"]; |
| - extra_data.capabilities = cast_channel::CastDeviceCapability::AUDIO_OUT; |
| - if (!audio_only) |
| - extra_data.capabilities |= cast_channel::CastDeviceCapability::VIDEO_OUT; |
| - extra_data.cast_channel_id = channel_id; |
| + extra_data.port = port; |
| + extra_data.discovered_by_dial = false; |
| cast_sink->set_sink(sink); |
| cast_sink->set_cast_data(extra_data); |
| @@ -80,6 +80,22 @@ ErrorType CreateCastMediaSink(const media_router::DnsSdService& service, |
| return ErrorType::NONE; |
| } |
| +static media_router::MediaSinkInternal CreateCastSinkFromDialSink( |
| + const media_router::MediaSinkInternal& dial_sink) { |
| + std::string unique_id = dial_sink.sink().id(); |
| + std::string friendly_name = dial_sink.sink().name(); |
| + media_router::MediaSink sink(unique_id, friendly_name, |
| + media_router::MediaSink::IconType::CAST); |
| + |
| + media_router::CastSinkExtraData extra_data; |
| + extra_data.ip_address = dial_sink.dial_data().ip_address; |
| + extra_data.port = media_router::CastMediaSinkService::kCastControlPort; |
| + extra_data.model_name = dial_sink.dial_data().model_name; |
| + extra_data.discovered_by_dial = true; |
| + |
| + return media_router::MediaSinkInternal(sink, extra_data); |
| +} |
| + |
| } // namespace |
| namespace media_router { |
| @@ -87,6 +103,9 @@ namespace media_router { |
| // static |
| const char CastMediaSinkService::kCastServiceType[] = "_googlecast._tcp.local"; |
| +// static |
| +int CastMediaSinkService::kCastControlPort = 8009; |
| + |
| CastMediaSinkService::CastMediaSinkService( |
| const OnSinksDiscoveredCallback& callback, |
| content::BrowserContext* browser_context) |
| @@ -138,6 +157,23 @@ void CastMediaSinkService::SetDnsSdRegistryForTest(DnsSdRegistry* registry) { |
| MediaSinkServiceBase::StartTimer(); |
| } |
| +void CastMediaSinkService::OnFetchCompleted() { |
| + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| + |
| + MediaSinkServiceBase::RemoveSinks(); |
| + |
| + // Copy cast sink from mDNS service to |current_sinks_|. |
| + for (const auto& sink_it : current_sinks_by_mdns_map_) |
| + MediaSinkServiceBase::AddSink(sink_it.second); |
| + |
| + // Copy cast sink from DIAL discovery to |current_sinks_|. |
| + for (const auto& sink_it : current_sinks_by_dial_map_) { |
| + if (!base::ContainsKey(current_sinks_by_mdns_map_, sink_it.first)) |
| + MediaSinkServiceBase::AddSink(sink_it.second); |
| + } |
| + MediaSinkServiceBase::OnFetchCompleted(); |
| +} |
| + |
| void CastMediaSinkService::OnDnsSdEvent( |
| const std::string& service_type, |
| const DnsSdRegistry::DnsSdServiceList& services) { |
| @@ -145,50 +181,74 @@ void CastMediaSinkService::OnDnsSdEvent( |
| DVLOG(2) << "CastMediaSinkService::OnDnsSdEvent found " << services.size() |
| << " services"; |
| - current_sinks_.clear(); |
| - current_services_ = services; |
| + current_sinks_by_mdns_map_.clear(); |
| + current_service_ip_endpoints_.clear(); |
| for (const auto& service : services) { |
| - net::IPAddress ip_address; |
| - if (!ip_address.AssignFromIPLiteral(service.ip_address)) { |
| - DVLOG(2) << "Invalid ip_addresss: " << service.ip_address; |
| + // Create Cast sink from mDNS service description. |
| + MediaSinkInternal cast_sink; |
| + ErrorType error = CreateCastMediaSink(service, &cast_sink); |
| + if (error != ErrorType::NONE) { |
| + DVLOG(2) << "Fail to create Cast device [error]: " << error; |
| continue; |
| } |
| - net::HostPortPair host_port_pair = |
| - net::HostPortPair::FromString(service.service_host_port); |
| + net::IPEndPoint ip_endpoint(cast_sink.cast_data().ip_address, |
| + cast_sink.cast_data().port); |
| + current_service_ip_endpoints_.insert(ip_endpoint); |
| + |
| + // Open Cast socket on the IO thread. |
| content::BrowserThread::PostTask( |
| content::BrowserThread::IO, FROM_HERE, |
| - base::Bind(&CastMediaSinkService::OpenChannelOnIOThread, this, service, |
| - net::IPEndPoint(ip_address, host_port_pair.port()))); |
| + base::Bind(&CastMediaSinkService::OpenChannelOnIOThread, this, |
| + ip_endpoint, |
| + base::Bind(&CastMediaSinkService::OnChannelOpenedOnIOThread, |
| + this, cast_sink))); |
| } |
| MediaSinkServiceBase::RestartTimer(); |
| } |
| +void CastMediaSinkService::OnMediaSinkAdded(const MediaSinkInternal& sink) { |
| + auto ip_address = sink.dial_data().ip_address; |
| + net::IPEndPoint ip_endpoint(ip_address, kCastControlPort); |
| + |
| + if (base::ContainsKey(current_service_ip_endpoints_, ip_endpoint)) { |
| + DVLOG(2) << "Sink discovered by mDNS, skip adding [name]: " |
| + << sink.sink().name(); |
| + return; |
| + } |
| + |
| + auto cast_sink = CreateCastSinkFromDialSink(sink); |
| + OpenChannelOnIOThread( |
| + ip_endpoint, base::Bind(&CastMediaSinkService::OnChannelOpenedOnIOThread, |
| + this, cast_sink)); |
|
imcheng
2017/07/06 22:53:30
We can enable moves for MediaSinkInternal to make
zhaobin
2017/07/10 20:21:15
Done.
|
| +} |
| + |
| +void CastMediaSinkService::OnMediaSinksRemoved() { |
| + current_sinks_by_dial_map_.clear(); |
| +} |
| + |
| void CastMediaSinkService::OpenChannelOnIOThread( |
| - const DnsSdService& service, |
| - const net::IPEndPoint& ip_endpoint) { |
| + const net::IPEndPoint& ip_endpoint, |
| + const cast_channel::CastSocket::OnOpenCallback& on_open_callback) { |
|
imcheng
2017/07/06 22:53:30
Does this need to take a callback as input, or can
zhaobin
2017/07/10 20:21:15
Done.
|
| auto* observer = cast_socket_service_->GetObserver(kObserverId); |
| if (!observer) { |
| observer = new CastSocketObserver(); |
| cast_socket_service_->AddObserver(kObserverId, base::WrapUnique(observer)); |
| } |
| - cast_socket_service_->OpenSocket( |
| - ip_endpoint, g_browser_process->net_log(), |
| - base::Bind(&CastMediaSinkService::OnChannelOpenedOnIOThread, this, |
| - service), |
| - observer); |
| + cast_socket_service_->OpenSocket(ip_endpoint, g_browser_process->net_log(), |
| + on_open_callback, observer); |
| } |
| void CastMediaSinkService::OnChannelOpenedOnIOThread( |
| - const DnsSdService& service, |
| + const MediaSinkInternal& cast_sink, |
| int channel_id, |
| cast_channel::ChannelError channel_error) { |
| if (channel_error != cast_channel::ChannelError::NONE) { |
| - DVLOG(2) << "Fail to open channel " << service.ip_address << ": " |
| - << service.service_host_port |
| + DVLOG(2) << "Fail to open channel " |
| + << cast_sink.cast_data().ip_address.ToString() |
| << " [ChannelError]: " << (int)channel_error; |
| return; |
| } |
| @@ -199,31 +259,40 @@ void CastMediaSinkService::OnChannelOpenedOnIOThread( |
| return; |
| } |
| + media_router::CastSinkExtraData extra_data = cast_sink.cast_data(); |
| + extra_data.capabilities = cast_channel::CastDeviceCapability::AUDIO_OUT; |
| + if (!socket->audio_only()) |
| + extra_data.capabilities |= cast_channel::CastDeviceCapability::VIDEO_OUT; |
| + extra_data.cast_channel_id = channel_id; |
| + |
| content::BrowserThread::PostTask( |
| content::BrowserThread::UI, FROM_HERE, |
| base::Bind(&CastMediaSinkService::OnChannelOpenedOnUIThread, this, |
| - service, channel_id, socket->audio_only())); |
| + MediaSinkInternal(cast_sink.sink(), extra_data))); |
| } |
| void CastMediaSinkService::OnChannelOpenedOnUIThread( |
| - const DnsSdService& service, |
| - int channel_id, |
| - bool audio_only) { |
| + const MediaSinkInternal& cast_sink) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| - MediaSinkInternal sink; |
| - ErrorType error = CreateCastMediaSink(service, channel_id, audio_only, &sink); |
| - if (error != ErrorType::NONE) { |
| - DVLOG(2) << "Fail to create Cast device [error]: " << error; |
| - return; |
| + auto ip_endpoint = net::IPEndPoint(cast_sink.cast_data().ip_address, |
| + cast_sink.cast_data().port); |
| + |
| + // Skip adding if IP address not found in current round of mDNS discovery. |
| + if (!cast_sink.cast_data().discovered_by_dial) { |
| + if (!base::ContainsValue(current_service_ip_endpoints_, ip_endpoint)) { |
| + DVLOG(2) << "Service data not found in current service data list..."; |
| + return; |
| + } |
| } |
| - if (!base::ContainsValue(current_services_, service)) { |
| - DVLOG(2) << "Service data not found in current service data list..."; |
| - return; |
| + DVLOG(2) << "Ading sink to current_sinks_ [name]: " |
| + << cast_sink.sink().name(); |
| + // Add or update existing cast sink. |
| + if (cast_sink.cast_data().discovered_by_dial) { |
| + current_sinks_by_dial_map_[ip_endpoint] = cast_sink; |
| + } else { |
| + current_sinks_by_mdns_map_[ip_endpoint] = cast_sink; |
| } |
| - |
| - DVLOG(2) << "Ading sink to current_sinks_ [id]: " << sink.sink().id(); |
| - current_sinks_.insert(sink); |
| MediaSinkServiceBase::RestartTimer(); |
| } |