| 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..6e349adbdeb9430d23142fc4839c708871e8ff1e 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,12 @@ ErrorType CreateCastMediaSink(const media_router::DnsSdService& service,
|
| if (!ip_address.AssignFromIPLiteral(service.ip_address))
|
| return ErrorType::MISSING_OR_INVALID_IP_ADDRESS;
|
|
|
| + // TODO(zhaobin): Make DnsSdService's service_host_port take net::HostPortPair
|
| + // type instead of plain string.
|
| + 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 +73,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 +82,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,11 +105,14 @@ namespace media_router {
|
| // static
|
| const char CastMediaSinkService::kCastServiceType[] = "_googlecast._tcp.local";
|
|
|
| +// static
|
| +const int CastMediaSinkService::kCastControlPort = 8009;
|
| +
|
| CastMediaSinkService::CastMediaSinkService(
|
| const OnSinksDiscoveredCallback& callback,
|
| content::BrowserContext* browser_context)
|
| : MediaSinkServiceBase(callback) {
|
| - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| cast_socket_service_ = cast_channel::CastSocketServiceFactory::GetInstance()
|
| ->GetForBrowserContext(browser_context);
|
| DCHECK(cast_socket_service_);
|
| @@ -102,14 +123,14 @@ CastMediaSinkService::CastMediaSinkService(
|
| cast_channel::CastSocketService* cast_socket_service)
|
| : MediaSinkServiceBase(callback),
|
| cast_socket_service_(cast_socket_service) {
|
| - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| DCHECK(cast_socket_service_);
|
| }
|
|
|
| CastMediaSinkService::~CastMediaSinkService() {}
|
|
|
| void CastMediaSinkService::Start() {
|
| - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| if (dns_sd_registry_)
|
| return;
|
|
|
| @@ -120,7 +141,7 @@ void CastMediaSinkService::Start() {
|
| }
|
|
|
| void CastMediaSinkService::Stop() {
|
| - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| if (!dns_sd_registry_)
|
| return;
|
|
|
| @@ -138,57 +159,132 @@ void CastMediaSinkService::SetDnsSdRegistryForTest(DnsSdRegistry* registry) {
|
| MediaSinkServiceBase::StartTimer();
|
| }
|
|
|
| +void CastMediaSinkService::OnFetchCompleted() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| + auto task_runner = content::BrowserThread::GetTaskRunnerForThread(
|
| + content::BrowserThread::IO);
|
| + base::PostTaskAndReplyWithResult(
|
| + task_runner.get(), FROM_HERE,
|
| + base::BindOnce(&CastMediaSinkService::GetCastSinksOnIOThread, this),
|
| + base::BindOnce(&CastMediaSinkService::OnFetchCompletedOnUIThread, this));
|
| +}
|
| +
|
| +std::set<MediaSinkInternal> CastMediaSinkService::GetCastSinksOnIOThread() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| +
|
| + std::set<MediaSinkInternal> sinks;
|
| + // Copy cast sink from mDNS service to |current_sinks_|.
|
| + for (const auto& sink_it : current_sinks_by_mdns_) {
|
| + DVLOG(2) << "Discovered by mdns [name]: " << sink_it.second.sink().name();
|
| + sinks.insert(sink_it.second);
|
| + }
|
| +
|
| + // Copy cast sink from DIAL discovery to |current_sinks_|.
|
| + for (const auto& sink_it : current_sinks_by_dial_) {
|
| + DVLOG(2) << "Discovered by dial [name]: " << sink_it.second.sink().name();
|
| + if (!base::ContainsKey(current_sinks_by_mdns_, sink_it.first))
|
| + sinks.insert(sink_it.second);
|
| + }
|
| + return sinks;
|
| +}
|
| +
|
| +void CastMediaSinkService::OnFetchCompletedOnUIThread(
|
| + std::set<MediaSinkInternal> cast_sinks) {
|
| + MediaSinkServiceBase::current_sinks_ = cast_sinks;
|
| + MediaSinkServiceBase::OnFetchCompleted();
|
| +}
|
| +
|
| void CastMediaSinkService::OnDnsSdEvent(
|
| const std::string& service_type,
|
| const DnsSdRegistry::DnsSdServiceList& services) {
|
| - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| DVLOG(2) << "CastMediaSinkService::OnDnsSdEvent found " << services.size()
|
| << " services";
|
|
|
| - current_sinks_.clear();
|
| - current_services_ = services;
|
| -
|
| + std::vector<MediaSinkInternal> cast_sinks;
|
| 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);
|
|
|
| - content::BrowserThread::PostTask(
|
| - content::BrowserThread::IO, FROM_HERE,
|
| - base::Bind(&CastMediaSinkService::OpenChannelOnIOThread, this, service,
|
| - net::IPEndPoint(ip_address, host_port_pair.port())));
|
| + cast_sinks.push_back(std::move(cast_sink));
|
| }
|
|
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&CastMediaSinkService::OpenChannelsOnIOThread, this,
|
| + std::move(cast_sinks)));
|
| +
|
| MediaSinkServiceBase::RestartTimer();
|
| }
|
|
|
| +void CastMediaSinkService::OpenChannelsOnIOThread(
|
| + std::vector<MediaSinkInternal> cast_sinks) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| +
|
| + current_sinks_by_mdns_.clear();
|
| + current_service_ip_endpoints_.clear();
|
| +
|
| + for (const auto& cast_sink : cast_sinks) {
|
| + net::IPEndPoint ip_endpoint(cast_sink.cast_data().ip_address,
|
| + cast_sink.cast_data().port);
|
| + current_service_ip_endpoints_.insert(ip_endpoint);
|
| +
|
| + OpenChannelOnIOThread(ip_endpoint, cast_sink);
|
| + }
|
| +}
|
| +
|
| +void CastMediaSinkService::OnDialSinkAdded(const MediaSinkInternal& sink) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| +
|
| + 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;
|
| + }
|
| +
|
| + OpenChannelOnIOThread(ip_endpoint, CreateCastSinkFromDialSink(sink));
|
| +}
|
| +
|
| +void CastMediaSinkService::OnDialSinksRemoved() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| +
|
| + current_sinks_by_dial_.clear();
|
| +}
|
| +
|
| void CastMediaSinkService::OpenChannelOnIOThread(
|
| - const DnsSdService& service,
|
| - const net::IPEndPoint& ip_endpoint) {
|
| + const net::IPEndPoint& ip_endpoint,
|
| + MediaSinkInternal cast_sink) {
|
| auto* observer = cast_socket_service_->GetObserver(kObserverId);
|
| if (!observer) {
|
| observer = new CastSocketObserver();
|
| cast_socket_service_->AddObserver(kObserverId, base::WrapUnique(observer));
|
| }
|
|
|
| + // TODO(zhaobin): Use base::BindOnce instead of base::Bind here.
|
| cast_socket_service_->OpenSocket(
|
| ip_endpoint, g_browser_process->net_log(),
|
| base::Bind(&CastMediaSinkService::OnChannelOpenedOnIOThread, this,
|
| - service),
|
| + std::move(cast_sink)),
|
| observer);
|
| }
|
|
|
| void CastMediaSinkService::OnChannelOpenedOnIOThread(
|
| - const DnsSdService& service,
|
| + 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()
|
| + << " [name]: " << cast_sink.sink().name()
|
| << " [ChannelError]: " << (int)channel_error;
|
| return;
|
| }
|
| @@ -199,32 +295,38 @@ void CastMediaSinkService::OnChannelOpenedOnIOThread(
|
| return;
|
| }
|
|
|
| - content::BrowserThread::PostTask(
|
| - content::BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&CastMediaSinkService::OnChannelOpenedOnUIThread, this,
|
| - service, channel_id, socket->audio_only()));
|
| -}
|
| -
|
| -void CastMediaSinkService::OnChannelOpenedOnUIThread(
|
| - const DnsSdService& service,
|
| - int channel_id,
|
| - bool audio_only) {
|
| - 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;
|
| + // Skip adding if IP address not found in current round of mDNS discovery.
|
| + net::IPEndPoint ip_endpoint(cast_sink.cast_data().ip_address,
|
| + cast_sink.cast_data().port);
|
| + if (!cast_sink.cast_data().discovered_by_dial) {
|
| + if (current_service_ip_endpoints_.find(ip_endpoint) ==
|
| + current_service_ip_endpoints_.end()) {
|
| + DVLOG(2) << "Service data not found in current service data list..."
|
| + << ip_endpoint.ToString();
|
| + return;
|
| + }
|
| }
|
|
|
| - if (!base::ContainsValue(current_services_, service)) {
|
| - DVLOG(2) << "Service data not found in current service data list...";
|
| - 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;
|
| +
|
| + MediaSinkInternal updated_sink(cast_sink.sink(), extra_data);
|
| + DVLOG(2) << "Ading sink to current_sinks_ [name]: "
|
| + << updated_sink.sink().name();
|
| +
|
| + // Add or update existing cast sink.
|
| + if (updated_sink.cast_data().discovered_by_dial) {
|
| + current_sinks_by_dial_[ip_endpoint] = updated_sink;
|
| + } else {
|
| + current_sinks_by_mdns_[ip_endpoint] = updated_sink;
|
| }
|
|
|
| - DVLOG(2) << "Ading sink to current_sinks_ [id]: " << sink.sink().id();
|
| - current_sinks_.insert(sink);
|
| - MediaSinkServiceBase::RestartTimer();
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&CastMediaSinkService::RestartTimer, this));
|
| }
|
|
|
| CastMediaSinkService::CastSocketObserver::CastSocketObserver() {}
|
|
|