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

Unified Diff: chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc

Issue 2965843002: [Media Router] Support dual discovery (Closed)
Patch Set: clean up and fix unit tests 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 side-by-side diff with in-line comments
Download patch
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();
}

Powered by Google App Engine
This is Rietveld 408576698