Index: chrome/browser/media/router/dial_media_sink_cache_service.cc |
diff --git a/chrome/browser/media/router/dial_media_sink_cache_service.cc b/chrome/browser/media/router/dial_media_sink_cache_service.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c2c8e2d799040d1edb9839f00307b2c909fa3e52 |
--- /dev/null |
+++ b/chrome/browser/media/router/dial_media_sink_cache_service.cc |
@@ -0,0 +1,107 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/media/router/dial_media_sink_cache_service.h" |
+ |
+#include "base/time/time.h" |
+#include "chrome/browser/extensions/api/dial/device_description_fetcher.h" |
+#include "chrome/browser/extensions/api/dial/dial_api.h" |
+#include "chrome/browser/extensions/api/dial/dial_api_factory.h" |
+#include "chrome/browser/extensions/api/dial/dial_device_data.h" |
+#include "chrome/browser/media/router/media_sinks_observer.h" |
+#include "chrome/browser/media/router/mojo/media_router_mojo_impl.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "content/public/browser/browser_thread.h" |
+ |
+using base::Time; |
+using base::TimeDelta; |
+ |
+namespace { |
+// The maximum time a response is expected after a M-SEARCH request. |
+const int kSinkAliveTimeoutSecs = 2; |
+} |
+ |
+namespace media_router { |
+ |
+DialMediaSinkCacheService::DialMediaSinkCacheService() {} |
+DialMediaSinkCacheService::~DialMediaSinkCacheService() {} |
+ |
+std::vector<MediaSinkInternal> DialMediaSinkCacheService::GetAliveSinks() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ std::vector<MediaSinkInternal> alive_sinks; |
+ for (const auto& sink_it : cached_sinks_) { |
+ if (IsAlive(sink_it.second)) |
+ alive_sinks.push_back(sink_it.second.sink); |
+ } |
+ return alive_sinks; |
+} |
+ |
+void DialMediaSinkCacheService::PruneInactiveSinks( |
+ bool network_connected, |
+ DeviceDescriptionService* description_service, |
+ net::URLRequestContextGetter* request_context) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (!network_connected) |
+ return; |
+ |
+ for (const auto& sink_it : cached_sinks_) { |
+ if (IsAlive(sink_it.second)) |
+ continue; |
+ |
+ description_service->CheckAccess( |
+ sink_it.second.description_url, request_context, |
+ base::Bind(&DialMediaSinkCacheService::OnCheckAccessCompleted, |
+ base::Unretained(this), sink_it.first)); |
+ } |
+} |
+ |
+void DialMediaSinkCacheService::OnCheckAccessCompleted( |
+ const std::string& sink_id, |
+ bool is_accessible) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (!is_accessible) |
+ cached_sinks_.erase(sink_id); |
+} |
+ |
+bool DialMediaSinkCacheService::AddOrUpdateSink( |
+ const DialDeviceDescription& device_description) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ MediaSink sink(device_description.unique_id, device_description.friendly_name, |
+ MediaSink::IconType::CAST); |
+ DialSinkExtraData extra_data; |
+ extra_data.app_url = device_description.app_url; |
+ extra_data.model_name = device_description.model_name; |
+ DCHECK( |
+ extra_data.ip_address.AssignFromIPLiteral(device_description.ip_address)); |
+ |
+ CachedDialMediaSink cached_sink; |
+ cached_sink.sink = MediaSinkInternal(sink, extra_data); |
+ cached_sink.last_update_time = base::Time::Now(); |
+ cached_sink.description_url = device_description.device_description_url; |
+ |
+ const auto& sink_it = cached_sinks_.find(sink.id()); |
+ if (sink_it == cached_sinks_.end()) { |
+ cached_sinks_.insert(std::make_pair(sink.id(), cached_sink)); |
+ } else { |
+ if (cached_sink.sink == sink_it->second.sink) |
+ return false; |
+ |
+ sink_it->second = cached_sink; |
+ } |
+ return true; |
+} |
+ |
+bool DialMediaSinkCacheService::IsAlive(const CachedDialMediaSink& sink) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ return sink.last_update_time + |
+ base::TimeDelta::FromSeconds(kSinkAliveTimeoutSecs) > |
+ base::Time::Now(); |
+} |
+ |
+} // namespace media_router |