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

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

Issue 2965843002: [Media Router] Support dual discovery (Closed)
Patch Set: resovle code review comments from Derek and Mark 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..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() {}

Powered by Google App Engine
This is Rietveld 408576698