#include "chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service.h"
#include "base/barrier_closure.h"
#include "base/functional/bind.h"
#include "base/ranges/algorithm.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "chrome/browser/media/router/discovery/access_code/access_code_cast_feature.h"
#include "chrome/browser/media/router/discovery/access_code/access_code_cast_pref_updater_impl.h"
#include "chrome/browser/media/router/discovery/access_code/access_code_media_sink_util.h"
#include "chrome/browser/media/router/discovery/discovery_network_monitor.h"
#include "chrome/browser/media/router/discovery/mdns/media_sink_util.h"
#include "chrome/browser/media/router/discovery/media_sink_discovery_metrics.h"
#include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "components/access_code_cast/common/access_code_cast_metrics.h"
#include "components/media_router/browser/media_router.h"
#include "components/media_router/browser/media_router_factory.h"
#include "components/media_router/common/discovery/media_sink_internal.h"
#include "components/media_router/common/media_route.h"
#include "components/media_router/common/media_sink.h"
#include "components/media_router/common/mojom/media_router.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chrome/browser/media/router/discovery/access_code/access_code_cast_pref_updater_lacros.h"
#include "chromeos/lacros/crosapi_pref_observer.h"
#endif
namespace media_router {
namespace {
const int kConnectTimeoutInSeconds = …;
const int kPingIntervalInSeconds = …;
const int kLivenessTimeoutInSeconds = …;
SinkSource;
ChannelOpenedCallback;
constexpr char kLoggerComponent[] = …;
}
bool IsAccessCodeCastEnabled() { … }
void AddRememberedSinkMetricsCallback(AddSinkResultCode result,
std::optional<std::string> unused) { … }
AccessCodeCastSinkService::AccessCodeCastSinkService(
Profile* profile,
MediaRouter* media_router,
CastMediaSinkServiceImpl* cast_media_sink_service_impl,
DiscoveryNetworkMonitor* network_monitor,
PrefService* prefs,
std::unique_ptr<AccessCodeCastPrefUpdater> pref_updater)
: … { … }
AccessCodeCastSinkService::AccessCodeCastSinkService(Profile* profile)
: … { … }
AccessCodeCastSinkService::~AccessCodeCastSinkService() = default;
base::WeakPtr<AccessCodeCastSinkService>
AccessCodeCastSinkService::GetWeakPtr() { … }
AccessCodeCastSinkService::AccessCodeMediaRoutesObserver::
AccessCodeMediaRoutesObserver(
MediaRouter* media_router,
AccessCodeCastSinkService* access_code_sink_service)
: … { … }
AccessCodeCastSinkService::AccessCodeMediaRoutesObserver::
~AccessCodeMediaRoutesObserver() = default;
void AccessCodeCastSinkService::AccessCodeMediaRoutesObserver::
OnRoutesUpdatedForTesting(const std::vector<MediaRoute>& routes) { … }
void AccessCodeCastSinkService::AccessCodeMediaRoutesObserver::OnRoutesUpdated(
const std::vector<MediaRoute>& routes) { … }
bool AccessCodeCastSinkService::IsSinkValidAccessCodeSink(
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::HandleMediaRouteRemovedByAccessCode(
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::HandleMediaRouteAdded(
const MediaRoute::Id route_id,
const bool is_route_local,
const MediaSource media_source,
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::OnAccessCodeRouteRemoved(
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::DiscoverSink(const std::string& access_code,
AddSinkResultCallback callback) { … }
void AccessCodeCastSinkService::AddSinkToMediaRouter(
const MediaSinkInternal& sink,
AddSinkResultCallback add_sink_callback) { … }
void AccessCodeCastSinkService::OnAccessCodeValidated(
AddSinkResultCallback add_sink_callback,
std::optional<DiscoveryDevice> discovery_device,
AddSinkResultCode result_code) { … }
void AccessCodeCastSinkService::OpenChannelIfNecessary(
const MediaSinkInternal& sink,
AddSinkResultCallback add_sink_callback,
bool has_sink) { … }
void AccessCodeCastSinkService::OpenChannelWithParams(
std::unique_ptr<net::BackoffEntry> backoff_entry,
const MediaSinkInternal& sink,
base::OnceCallback<void(bool)> channel_opened_cb,
cast_channel::CastSocketOpenParams open_params) { … }
std::optional<const MediaRoute> AccessCodeCastSinkService::GetActiveRoute(
const MediaSink::Id& sink_id) { … }
cast_channel::CastSocketOpenParams
AccessCodeCastSinkService::CreateCastSocketOpenParams(
const MediaSinkInternal& sink) { … }
void AccessCodeCastSinkService::OnChannelOpenedResult(
AddSinkResultCallback add_sink_callback,
const MediaSinkInternal& sink,
bool channel_opened) { … }
void AccessCodeCastSinkService::CheckMediaSinkForExpiration(
const MediaSink::Id& sink_id) { … }
bool AccessCodeCastSinkService::IsAccessCodeCastLacrosSyncEnabledForTesting() { … }
void AccessCodeCastSinkService::ShutdownForTesting() { … }
void AccessCodeCastSinkService::ResetPrefUpdaterForTesting() { … }
void AccessCodeCastSinkService::StoreSinkInPrefsForTesting(
base::OnceClosure on_sink_stored_callback,
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::SetExpirationTimerForTesting(
const MediaSink::Id& sink_id) { … }
void AccessCodeCastSinkService::OpenChannelIfNecessaryForTesting(
const MediaSinkInternal& sink,
AddSinkResultCallback add_sink_callback,
bool has_sink) { … }
void AccessCodeCastSinkService::HandleMediaRouteAddedForTesting(
const MediaRoute::Id route_id,
const bool is_route_local,
const MediaSource media_source,
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::HandleMediaRouteRemovedByAccessCodeForTesting(
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::OnAccessCodeValidatedForTesting(
AddSinkResultCallback add_sink_callback,
std::optional<DiscoveryDevice> discovery_device,
AddSinkResultCode result_code) { … }
void AccessCodeCastSinkService::OnChannelOpenedResultForTesting(
AddSinkResultCallback add_sink_callback,
const MediaSinkInternal& sink,
bool channel_opened) { … }
void AccessCodeCastSinkService::InitializePrefUpdaterForTesting() { … }
void AccessCodeCastSinkService::InitAllStoredDevicesForTesting() { … }
void AccessCodeCastSinkService::CalculateDurationTillExpirationForTesting(
const MediaSink::Id& sink_id,
base::OnceCallback<void(base::TimeDelta)> on_duration_calculated_callback) { … }
void AccessCodeCastSinkService::DoCheckMediaSinkForExpiration(
const MediaSink::Id& sink_id,
base::TimeDelta time_till_expiration) { … }
void AccessCodeCastSinkService::OnObserverRoutesUpdatedForTesting(
const std::vector<MediaRoute>& routes) { … }
void AccessCodeCastSinkService::InitAllStoredDevices() { … }
void AccessCodeCastSinkService::OnStoredDevicesValidated(
const std::vector<MediaSinkInternal>& validated_devices) { … }
void AccessCodeCastSinkService::OnSyncedDevicesValidated(
const std::vector<MediaSinkInternal>& validated_sinks) { … }
void AccessCodeCastSinkService::FetchAndValidateStoredDevices(
base::OnceCallback<void(const std::vector<MediaSinkInternal>&)>
on_device_validated_callback) { … }
void AccessCodeCastSinkService::ValidateStoredDevices(
base::OnceCallback<void(const std::vector<MediaSinkInternal>&)>
on_device_validated_callback,
base::Value::Dict stored_sinks) { … }
void AccessCodeCastSinkService::InitExpirationTimers(
const std::vector<MediaSinkInternal>& cast_sinks) { … }
void AccessCodeCastSinkService::SetExpirationTimer(
const MediaSink::Id& sink_id) { … }
void AccessCodeCastSinkService::DoSetExpirationTimer(
const MediaSink::Id& sink_id,
base::TimeDelta time_till_expiration) { … }
void AccessCodeCastSinkService::ResetExpirationTimers() { … }
void AccessCodeCastSinkService::CalculateDurationTillExpiration(
const MediaSink::Id& sink_id,
base::OnceCallback<void(base::TimeDelta)> on_duration_calculated_callback) { … }
void AccessCodeCastSinkService::DoCalculateDurationTillExpiration(
const MediaSink::Id& sink_id,
base::OnceCallback<void(base::TimeDelta)> on_duration_calculated_callback,
std::optional<base::Time> fetched_device_added_time) { … }
void AccessCodeCastSinkService::OnExpiration(const MediaSink::Id& sink_id) { … }
void AccessCodeCastSinkService::ExpireSink(const MediaSink::Id& sink_id) { … }
void AccessCodeCastSinkService::StoreSinkInPrefsById(
const MediaSink::Id& sink_id,
base::OnceClosure on_sink_stored_callback) { … }
void AccessCodeCastSinkService::StoreSinkInPrefs(
base::OnceClosure on_sink_stored_callback,
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::StoreSinkAndSetExpirationTimer(
const MediaSink::Id& sink_id) { … }
void AccessCodeCastSinkService::AddStoredDevicesToMediaRouter(
const std::vector<MediaSinkInternal>& cast_sinks) { … }
void AccessCodeCastSinkService::UpdateExistingSink(
const MediaSinkInternal& new_sink,
const MediaSinkInternal* existing_sink) { … }
void AccessCodeCastSinkService::RemoveSinkIdFromAllEntries(
const MediaSink::Id& sink_id) { … }
void AccessCodeCastSinkService::RemoveAndDisconnectMediaSinkFromRouter(
const MediaSinkInternal* sink) { … }
void AccessCodeCastSinkService::RemoveAndDisconnectExistingSinksOnNetwork() { … }
void AccessCodeCastSinkService::LogInfo(const std::string& log_message,
const std::string& sink_id) { … }
void AccessCodeCastSinkService::LogWarning(const std::string& log_message,
const std::string& sink_id) { … }
void AccessCodeCastSinkService::LogError(const std::string& log_message,
const std::string& sink_id) { … }
void AccessCodeCastSinkService::OnNetworksChanged(
const std::string& network_id) { … }
void AccessCodeCastSinkService::OnDurationPrefChange() { … }
void AccessCodeCastSinkService::OnEnabledPrefChange() { … }
void AccessCodeCastSinkService::OnDevicesPrefChange() { … }
void AccessCodeCastSinkService::Shutdown() { … }
void AccessCodeCastSinkService::SetIdentityManagerForTesting(
signin::IdentityManager* identity_manager) { … }
void AccessCodeCastSinkService::InitializePrefUpdater() { … }
#if BUILDFLAG(IS_CHROMEOS_LACROS)
void AccessCodeCastSinkService::MaybeCreateAccessCodePrefUpdaterLacros(
bool is_pref_registered) {
if (is_pref_registered) {
lacros_device_sync_enabled_ = true;
pref_updater_ = std::make_unique<AccessCodeCastPrefUpdaterLacros>();
access_code_cast_devices_observer_ = std::make_unique<CrosapiPrefObserver>(
crosapi::mojom::PrefPath::kAccessCodeCastDevices,
base::BindRepeating(
&AccessCodeCastSinkService::OnAccessCodeCastDevicesChanged,
base::Unretained(this)));
} else {
pref_updater_ = std::make_unique<AccessCodeCastPrefUpdaterImpl>(prefs_);
}
InitAllStoredDevices();
}
void AccessCodeCastSinkService::OnAccessCodeCastDevicesChanged(
base::Value value) {
if (value.is_dict()) {
ValidateStoredDevices(
base::BindOnce(&AccessCodeCastSinkService::OnSyncedDevicesValidated,
weak_ptr_factory_.GetWeakPtr()),
std::move(value).TakeDict());
}
}
#endif
bool AccessCodeCastSinkService::IsAccessCodeCastLacrosSyncEnabled() { … }
}