Commit a2c4428d authored by Kartik Hegde's avatar Kartik Hegde Committed by Chromium LUCI CQ

Reland "network_diagnostics: Add VideoConferencing routine"

This reverts commit d5e51b0e.

Reason for revert: Fix MSan issue

The following on the original CL caused an MSan issue:

`const GURL& url = media_hostnames_.back();
 media_hostnames_.pop_back();`

A reference to the URL is taken and then immediately after the URL is
deleted. The fix removes access to the deleted memory.

Original change's description:
> Revert "network_diagnostics: Add VideoConferencing routine"
>
> This reverts commit 2f0a1300.
>
> Reason for revert: VideoConferencingRoutineTest fails on MSan bot due to use-of-uninitialized-value:
> https://ci.chromium.org/p/chromium/builders/ci/Linux%20ChromiumOS%20MSan%20Tests/21568
>
> Original change's description:
> > network_diagnostics: Add VideoConferencing routine
> >
> > Tests for successful UDP and TCP connections to a STUN server and
> > whether several Google media hostnames are reachable.
> >
> > BUG=b/172994051
> > TEST=unit_tests --gtest_filter=VideoConferencingRoutineTest.*
> >
> > Change-Id: I64d2784c3b3ae111c9e924b1296a5463dcb7cea2
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2535997
> > Commit-Queue: Kartik Hegde <khegde@chromium.org>
> > Reviewed-by: Steven Bennetts <stevenjb@chromium.org>
> > Reviewed-by: Hugo Benichi <hugobenichi@google.com>
> > Reviewed-by: Daniel Cheng <dcheng@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#833465}
>
> TBR=stevenjb@chromium.org,dcheng@chromium.org,hugobenichi@google.com,khegde@chromium.org,chromium-scoped@luci-project-accounts.iam.gserviceaccount.com
>
> Change-Id: I6d4f020371052227ab20ab45c3ffe85bb6f57310
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: b/172994051
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2573557
> Reviewed-by: Kunihiko Sakamoto <ksakamoto@chromium.org>
> Commit-Queue: Kunihiko Sakamoto <ksakamoto@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#833611}

TBR=stevenjb@chromium.org,dcheng@chromium.org,ksakamoto@chromium.org,hugobenichi@google.com,khegde@chromium.org,chromium-scoped@luci-project-accounts.iam.gserviceaccount.com

# Not skipping CQ checks because this is a reland.

Bug: b/172994051
Change-Id: Iaf12c4be3e9776188c545b2a792557bb9549edf0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2575365Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKartik Hegde <khegde@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Commit-Queue: Kartik Hegde <khegde@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834057}
parent 13e83065
......@@ -2027,6 +2027,8 @@ source_set("chromeos") {
"net/network_diagnostics/tls_prober.h",
"net/network_diagnostics/udp_prober.cc",
"net/network_diagnostics/udp_prober.h",
"net/network_diagnostics/video_conferencing_routine.cc",
"net/network_diagnostics/video_conferencing_routine.h",
"net/network_health/network_health.cc",
"net/network_health/network_health.h",
"net/network_health/network_health_localized_strings.cc",
......@@ -3663,6 +3665,7 @@ source_set("unit_tests") {
"net/network_diagnostics/signal_strength_routine_unittest.cc",
"net/network_diagnostics/tls_prober_unittest.cc",
"net/network_diagnostics/udp_prober_unittest.cc",
"net/network_diagnostics/video_conferencing_routine_unittest.cc",
"net/network_health/network_health_unittest.cc",
"net/network_portal_detector_impl_unittest.cc",
"net/network_pref_state_observer_unittest.cc",
......
......@@ -168,6 +168,26 @@ Problems:
* `kHighLatency`: HTTPS request latency is high.
* `kVeryHighLatency`: HTTPS request latency is very high.
#### VideoConferencing
Tests the device's video conferencing capabalities by testing whether the device
can:
1. Contact either a default or specified STUN server via UDP.
2. Contact either a default or specified STUN server via TCP.
3. Reach common media endpoints.
Problems:
* `kPotentialProblemUdpFailure`: Failed requests to a STUN server via UDP.
* `kPotentialProblemTcpFailure`: Failed requests to a STUN server via TCP.
* `kPotentialProblemMediaFailure`: Failed to establish a TLS connection to media hostnames.
* `kPotentialProblemUdpAndMediaFailure`: Failed requests to a STUN server via
UDP and failed to establish a TLS connection to media hostnames.
* `kUdpAndTcpFailure`: Failed requests to a STUN server via UDP and TCP.
* `kTcpAndMediaFailure`: Failed requests to a STUN server via TCP and failed to
established a TLS connection to media hostnames.
* `kUdpAndTcpAndMediaFailure`: Failed requests to a STUN server via UDP and TCP,
and failed to establish a TLS connection to media hostnames.
[Network Health and Configuration]: https://docs.google.com/document/d/10DSy-jZXaRo9I9aq1UqERy76t7HkgGvInWk57pHEkzg
[network_diagnostics.mojom]: https://source.chromium.org/chromium/chromium/src/+/master:chromeos/services/network_health/public/mojom/network_diagnostics.mojom?originalUrl=https:%2F%2Fcs.chromium.org%2F
[NetworkHealthService]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/chromeos/net/network_health/network_health_service.h?originalUrl=https:%2F%2Fcs.chromium.org%2F
......
......@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
#include "base/optional.h"
#include "chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.h"
#include "chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.h"
#include "chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h"
......@@ -19,6 +20,7 @@
#include "chrome/browser/chromeos/net/network_diagnostics/https_latency_routine.h"
#include "chrome/browser/chromeos/net/network_diagnostics/lan_connectivity_routine.h"
#include "chrome/browser/chromeos/net/network_diagnostics/signal_strength_routine.h"
#include "chrome/browser/chromeos/net/network_diagnostics/video_conferencing_routine.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
#include "components/device_event_log/device_event_log.h"
......@@ -209,5 +211,26 @@ void NetworkDiagnostics::HttpsLatency(HttpsLatencyCallback callback) {
std::move(routine), std::move(callback)));
}
void NetworkDiagnostics::VideoConferencing(
const base::Optional<std::string>& stun_server_name,
VideoConferencingCallback callback) {
auto routine = std::make_unique<VideoConferencingRoutine>();
if (stun_server_name.has_value()) {
routine =
std::make_unique<VideoConferencingRoutine>(stun_server_name.value());
}
// RunRoutine() takes a lambda callback that takes ownership of the routine.
// This ensures that the routine stays alive when it makes asynchronous mojo
// calls. The routine will be destroyed when the lambda exits.
routine->RunRoutine(base::BindOnce(
[](std::unique_ptr<VideoConferencingRoutine> routine,
VideoConferencingCallback callback, mojom::RoutineVerdict verdict,
const std::vector<mojom::VideoConferencingProblem>& problems,
const base::Optional<std::string>& support_details) {
std::move(callback).Run(verdict, problems, support_details);
},
std::move(routine), std::move(callback)));
}
} // namespace network_diagnostics
} // namespace chromeos
......@@ -5,7 +5,10 @@
#ifndef CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_NETWORK_DIAGNOSTICS_H_
#define CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_NETWORK_DIAGNOSTICS_H_
#include <string>
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
......@@ -39,6 +42,8 @@ class NetworkDiagnostics : public mojom::NetworkDiagnosticsRoutines {
void DnsResolution(DnsResolutionCallback callback) override;
void CaptivePortal(CaptivePortalCallback callback) override;
void HttpsLatency(HttpsLatencyCallback callback) override;
void VideoConferencing(const base::Optional<std::string>& stun_server_name,
VideoConferencingCallback callback) override;
private:
// An unowned pointer to the DebugDaemonClient instance.
......
......@@ -182,6 +182,35 @@ net::NetworkTrafficAnnotationTag GetStunNetworkAnnotationTag() {
)");
}
std::vector<int> GetUdpPortsForGoogleStunServer() {
return {19302, 19303, 19304, 19305, 19306, 19307, 19308, 19309};
}
std::vector<int> GetUdpPortsForCustomStunServer() {
return {3478};
}
std::vector<int> GetTcpPortsForGoogleStunServer() {
return {19305, 19306, 19307, 19308};
}
std::vector<int> GetTcpPortsForCustomStunServer() {
return {3478};
}
std::vector<GURL> GetDefaultMediaUrls() {
const char* const kHostnames[] = {
"https://apis.google.com", "https://talkgadget.google.com",
"https://clients6.google.com", "https://hangouts.google.com",
"https://client-channel.google.com", "https://googleapis.com",
"https://accounts.google.com", "https://clients4.google.com"};
std::vector<GURL> hostnames;
for (auto* const& hostname : kHostnames) {
hostnames.push_back(GURL(hostname));
}
return hostnames;
}
} // namespace util
} // namespace network_diagnostics
......
......@@ -90,6 +90,21 @@ const std::array<uint8_t, kStunHeaderSize>& GetStunHeader();
// Returns the traffic annotation tag for STUN traffic.
net::NetworkTrafficAnnotationTag GetStunNetworkAnnotationTag();
// Returns the ports used to speak to Google's STUN server over UDP.
std::vector<int> GetUdpPortsForGoogleStunServer();
// Returns the ports used to speak to a custom STUN server over UDP.
std::vector<int> GetUdpPortsForCustomStunServer();
// Returns the ports used to speak to Google's STUN server over TCP.
std::vector<int> GetTcpPortsForGoogleStunServer();
// Returns the ports used to speak to a custom STUN server over TCP.
std::vector<int> GetTcpPortsForCustomStunServer();
// Returns the list of urls related to Google media.
std::vector<GURL> GetDefaultMediaUrls();
} // namespace util
} // namespace network_diagnostics
......
......@@ -76,5 +76,11 @@ TEST(NetworkDiagnosticsUtilTest,
}
}
TEST(NetworkDiagnosticsUtilTest, TestDefaultMediaHostnamesAreValidUrls) {
for (const GURL& url : util::GetDefaultMediaUrls()) {
EXPECT_TRUE(url.is_valid());
}
}
} // namespace network_diagnostics
} // namespace chromeos
// Copyright 2020 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/chromeos/net/network_diagnostics/video_conferencing_routine.h"
#include <string>
#include <utility>
#include "base/logging.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_util.h"
#include "chrome/browser/chromeos/net/network_diagnostics/udp_prober.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/net_errors.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace chromeos {
namespace network_diagnostics {
namespace {
const char kDefaultStunServer[] = "stun.l.google.com";
} // namespace
const char kSupportDetails[] = "https://support.google.com/a/answer/1279090";
const base::TimeDelta kTimeoutAfterHostResolution =
base::TimeDelta::FromSeconds(10);
VideoConferencingRoutine::VideoConferencingRoutine()
: stun_server_hostname_(kDefaultStunServer),
udp_prober_getter_callback_(base::BindRepeating(
&VideoConferencingRoutine::CreateAndExecuteUdpProber)),
tls_prober_getter_callback_(base::BindRepeating(
&VideoConferencingRoutine::CreateAndExecuteTlsProber)),
udp_ports_(util::GetUdpPortsForGoogleStunServer()),
tcp_ports_(util::GetTcpPortsForGoogleStunServer()),
media_hostnames_(util::GetDefaultMediaUrls()) {}
VideoConferencingRoutine::VideoConferencingRoutine(
const std::string& stun_server_hostname)
: stun_server_hostname_(stun_server_hostname),
udp_prober_getter_callback_(base::BindRepeating(
&VideoConferencingRoutine::CreateAndExecuteUdpProber)),
tls_prober_getter_callback_(base::BindRepeating(
&VideoConferencingRoutine::CreateAndExecuteTlsProber)),
udp_ports_(util::GetUdpPortsForCustomStunServer()),
tcp_ports_(util::GetTcpPortsForCustomStunServer()),
media_hostnames_(util::GetDefaultMediaUrls()) {}
VideoConferencingRoutine::~VideoConferencingRoutine() = default;
void VideoConferencingRoutine::AnalyzeResultsAndExecuteCallback() {
base::Optional<std::string> support_details = kSupportDetails;
set_verdict(mojom::RoutineVerdict::kProblem);
if (!open_udp_port_found_) {
problems_.push_back(mojom::VideoConferencingProblem::kUdpFailure);
}
if (!open_tcp_port_found_) {
problems_.push_back(mojom::VideoConferencingProblem::kTcpFailure);
}
if (!media_hostnames_reachable_) {
problems_.push_back(mojom::VideoConferencingProblem::kMediaFailure);
}
if (problems_.empty()) {
set_verdict(mojom::RoutineVerdict::kNoProblem);
support_details = base::nullopt;
}
std::move(routine_completed_callback_)
.Run(verdict(), std::move(problems_), support_details);
}
void VideoConferencingRoutine::RunRoutine(
VideoConferencingRoutineCallback callback) {
if (!CanRun()) {
std::move(callback).Run(verdict(), std::move(problems_), base::nullopt);
return;
}
routine_completed_callback_ = std::move(callback);
ProbeStunServerOverUdp();
}
void VideoConferencingRoutine::ProbeStunServerOverUdp() {
if (udp_ports_.empty()) {
ProbeStunServerOverTcp();
return;
}
int port = udp_ports_.back();
udp_ports_.pop_back();
AttemptUdpProbe(net::HostPortPair(stun_server_hostname_, port));
}
void VideoConferencingRoutine::ProbeStunServerOverTcp() {
if (tcp_ports_.empty()) {
ProbeMediaHostnames();
return;
}
int port = tcp_ports_.back();
tcp_ports_.pop_back();
AttemptTcpProbe(net::HostPortPair(stun_server_hostname_, port));
}
void VideoConferencingRoutine::ProbeMediaHostnames() {
if (media_hostnames_.empty()) {
AnalyzeResultsAndExecuteCallback();
return;
}
auto host_pair = net::HostPortPair::FromURL(media_hostnames_.back());
media_hostnames_.pop_back();
AttemptTlsProbe(host_pair);
}
network::mojom::NetworkContext* VideoConferencingRoutine::GetNetworkContext() {
Profile* profile = util::GetUserProfile();
DCHECK(profile);
return content::BrowserContext::GetDefaultStoragePartition(profile)
->GetNetworkContext();
}
std::unique_ptr<UdpProber> VideoConferencingRoutine::CreateAndExecuteUdpProber(
UdpProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
base::span<const uint8_t> data,
net::NetworkTrafficAnnotationTag tag,
base::TimeDelta timeout_after_host_resolution,
UdpProber::UdpProbeCompleteCallback callback) {
return UdpProber::Start(std::move(network_context_getter), host_port_pair,
std::move(data), tag, timeout_after_host_resolution,
std::move(callback));
}
std::unique_ptr<TlsProber> VideoConferencingRoutine::CreateAndExecuteTlsProber(
TlsProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
bool negotiate_tls,
TlsProber::TlsProbeCompleteCallback callback) {
return std::make_unique<TlsProber>(std::move(network_context_getter),
host_port_pair, negotiate_tls,
std::move(callback));
}
void VideoConferencingRoutine::AttemptUdpProbe(
net::HostPortPair host_port_pair) {
// Store the instance of UdpProber.
udp_prober_ = udp_prober_getter_callback_.Run(
base::BindRepeating(&VideoConferencingRoutine::GetNetworkContext),
host_port_pair, util::GetStunHeader(),
util::GetStunNetworkAnnotationTag(), kTimeoutAfterHostResolution,
base::BindOnce(&VideoConferencingRoutine::OnUdpProbeComplete,
weak_ptr()));
}
void VideoConferencingRoutine::AttemptTcpProbe(
net::HostPortPair host_port_pair) {
tls_prober_ = tls_prober_getter_callback_.Run(
base::BindRepeating(&VideoConferencingRoutine::GetNetworkContext),
host_port_pair,
/*negotiate_tls=*/false,
base::BindOnce(&VideoConferencingRoutine::OnTcpProbeComplete,
weak_ptr()));
}
void VideoConferencingRoutine::AttemptTlsProbe(
net::HostPortPair host_port_pair) {
// Store the instance of TlsProber.
tls_prober_ = tls_prober_getter_callback_.Run(
base::BindRepeating(&VideoConferencingRoutine::GetNetworkContext),
host_port_pair,
/*negotiate_tls=*/true,
base::BindOnce(&VideoConferencingRoutine::OnTlsProbeComplete,
weak_ptr()));
}
void VideoConferencingRoutine::OnUdpProbeComplete(
int result,
UdpProber::ProbeExitEnum probe_exit_enum) {
if (result == net::OK) {
open_udp_port_found_ = true;
// Only one open UDP port needs to be detected.
ProbeStunServerOverTcp();
return;
}
ProbeStunServerOverUdp();
}
void VideoConferencingRoutine::OnTcpProbeComplete(
int result,
TlsProber::ProbeExitEnum probe_exit_enum) {
if (result == net::OK) {
open_tcp_port_found_ = true;
// Only one open TCP port needs to be detected.
ProbeMediaHostnames();
return;
}
ProbeStunServerOverTcp();
}
void VideoConferencingRoutine::OnTlsProbeComplete(
int result,
TlsProber::ProbeExitEnum probe_exit_enum) {
if (result != net::OK) {
media_hostnames_reachable_ = false;
// All media hostnames must be reachable.
AnalyzeResultsAndExecuteCallback();
return;
}
ProbeMediaHostnames();
}
} // namespace network_diagnostics
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_VIDEO_CONFERENCING_ROUTINE_H_
#define CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_VIDEO_CONFERENCING_ROUTINE_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/containers/span.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_routine.h"
#include "chrome/browser/chromeos/net/network_diagnostics/tls_prober.h"
#include "chrome/browser/chromeos/net/network_diagnostics/udp_prober.h"
#include "net/base/net_errors.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/gurl.h"
namespace chromeos {
namespace network_diagnostics {
extern const char kSupportDetails[];
extern const base::TimeDelta kTimeoutAfterHostResolution;
// Tests the device's video conferencing capabilities by testing the connection
// to a sample of Google servers used in various GVC offerings. See the
// README.md file for more details.
class VideoConferencingRoutine : public NetworkDiagnosticsRoutine {
public:
using VideoConferencingRoutineCallback =
mojom::NetworkDiagnosticsRoutines::VideoConferencingCallback;
using UdpProberGetterCallback =
base::RepeatingCallback<std::unique_ptr<UdpProber>(
UdpProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
base::span<const uint8_t> data,
net::NetworkTrafficAnnotationTag tag,
base::TimeDelta timeout_after_host_resolution,
UdpProber::UdpProbeCompleteCallback callback)>;
using TlsProberGetterCallback =
base::RepeatingCallback<std::unique_ptr<TlsProber>(
TlsProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
bool negotiate_tls,
TlsProber::TlsProbeCompleteCallback callback)>;
// Creates a routine using a default STUN server.
VideoConferencingRoutine();
// Creates a routine using a custom STUN server.
explicit VideoConferencingRoutine(const std::string& stun_server_hostname);
VideoConferencingRoutine(const VideoConferencingRoutine&) = delete;
VideoConferencingRoutine& operator=(const VideoConferencingRoutine&) = delete;
~VideoConferencingRoutine() override;
// NetworkDiagnosticsRoutine:
void AnalyzeResultsAndExecuteCallback() override;
// Run the core logic of this routine. Set |callback| to
// |routine_completed_callback_|, which is to be executed in
// AnalyzeResultsAndExecuteCallback().
void RunRoutine(VideoConferencingRoutineCallback callback);
void set_udp_prober_getter_callback_for_testing(
UdpProberGetterCallback udp_prober_getter_callback) {
udp_prober_getter_callback_ = std::move(udp_prober_getter_callback);
}
void set_tls_prober_getter_callback_for_testing(
TlsProberGetterCallback tls_prober_getter_callback) {
tls_prober_getter_callback_ = std::move(tls_prober_getter_callback);
}
private:
// Probes the STUN server over UDP to determine whether an open port
// connection exists.
void ProbeStunServerOverUdp();
// Probes the STUN server over TCP to determine whether an open port
// connection exists.
void ProbeStunServerOverTcp();
// Probes media endpoints over TCP with TLS.
void ProbeMediaHostnames();
// Returns the network context.
static network::mojom::NetworkContext* GetNetworkContext();
// Creates and instance of UdpProber.
static std::unique_ptr<UdpProber> CreateAndExecuteUdpProber(
UdpProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
base::span<const uint8_t> data,
net::NetworkTrafficAnnotationTag tag,
base::TimeDelta timeout_after_host_resolution,
UdpProber::UdpProbeCompleteCallback callback);
// Creates an instance of TlsProber.
static std::unique_ptr<TlsProber> CreateAndExecuteTlsProber(
TlsProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
bool negotiate_tls,
TlsProber::TlsProbeCompleteCallback callback);
// Launches a UDP probe.
void AttemptUdpProbe(net::HostPortPair host_port_pair);
// Launches a TCP probe.
void AttemptTcpProbe(net::HostPortPair host_port_pair);
// Launches a TLS probe.
void AttemptTlsProbe(net::HostPortPair host_port_pair);
// Handles UDP probe completion.
void OnUdpProbeComplete(int result, UdpProber::ProbeExitEnum probe_exit_enum);
// Handles TCP probe completion.
void OnTcpProbeComplete(int result, TlsProber::ProbeExitEnum probe_exit_enum);
// Handles TLS probe completion.
void OnTlsProbeComplete(int result, TlsProber::ProbeExitEnum probe_exit_enum);
// Returns the weak pointer to |this|.
base::WeakPtr<VideoConferencingRoutine> weak_ptr() {
return weak_factory_.GetWeakPtr();
}
std::vector<mojom::VideoConferencingProblem> problems_;
VideoConferencingRoutineCallback routine_completed_callback_;
std::string stun_server_hostname_;
bool open_udp_port_found_ = false;
bool open_tcp_port_found_ = false;
bool media_hostnames_reachable_ = true;
UdpProberGetterCallback udp_prober_getter_callback_;
TlsProberGetterCallback tls_prober_getter_callback_;
std::unique_ptr<UdpProber> udp_prober_;
std::unique_ptr<TlsProber> tls_prober_;
std::vector<int> udp_ports_;
std::vector<int> tcp_ports_;
std::vector<GURL> media_hostnames_;
base::WeakPtrFactory<VideoConferencingRoutine> weak_factory_{this};
};
} // namespace network_diagnostics
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_VIDEO_CONFERENCING_ROUTINE_H_
// Copyright 2020 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/chromeos/net/network_diagnostics/video_conferencing_routine.h"
#include <deque>
#include <memory>
#include <string>
#include <utility>
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_util.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace network_diagnostics {
namespace {
// Test implementation of UdpProber.
class TestUdpProber final : public UdpProber {
public:
TestUdpProber(UdpProber::UdpProbeCompleteCallback callback,
int result,
UdpProber::ProbeExitEnum probe_exit_enum) {
// Post an asynchronus task simulating a completed probe. This mimics the
// behavior of the production UdpProber constructor since the TestUdpProber
// instance will be complete before FinishProbe is invoked. In the
// production UdpProber, the constructor completes before DNS host
// resolution is complete.
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&TestUdpProber::FinishProbe, weak_factory_.GetWeakPtr(),
std::move(callback), result, probe_exit_enum));
}
TestUdpProber(const TestUdpProber&) = delete;
TestUdpProber& operator=(const TestUdpProber&) = delete;
~TestUdpProber() override = default;
private:
void FinishProbe(UdpProber::UdpProbeCompleteCallback callback,
int result,
UdpProber::ProbeExitEnum probe_exit_enum) {
std::move(callback).Run(result, probe_exit_enum);
}
base::WeakPtrFactory<TestUdpProber> weak_factory_{this};
};
// Test implementation of TlsProber.
class TestTlsProber final : public TlsProber {
public:
TestTlsProber(TlsProber::TlsProbeCompleteCallback callback,
int result,
TlsProber::ProbeExitEnum probe_exit_enum) {
// Post an asynchronus task simulating a completed probe. This mimics the
// behavior of the production TlsProber constructor since the TestTlsProber
// instance will be complete before FinishProbe is invoked. In the
// production TlsProber, the constructor completes before DNS host
// resolution is complete.
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&TestTlsProber::FinishProbe, weak_factory_.GetWeakPtr(),
std::move(callback), result, probe_exit_enum));
}
TestTlsProber(const TestTlsProber&) = delete;
TestTlsProber& operator=(const TestTlsProber&) = delete;
~TestTlsProber() override = default;
private:
void FinishProbe(TlsProber::TlsProbeCompleteCallback callback,
int result,
TlsProber::ProbeExitEnum probe_exit_enum) {
std::move(callback).Run(result, probe_exit_enum);
}
base::WeakPtrFactory<TestTlsProber> weak_factory_{this};
};
} // namespace
class VideoConferencingRoutineTest : public ::testing::Test {
public:
struct UdpProberReturnValue {
net::Error result;
UdpProber::ProbeExitEnum probe_exit_enum;
};
struct TlsProberReturnValue {
net::Error result;
TlsProber::ProbeExitEnum probe_exit_enum;
};
VideoConferencingRoutineTest() = default;
VideoConferencingRoutineTest(const VideoConferencingRoutineTest&) = delete;
VideoConferencingRoutineTest& operator=(const VideoConferencingRoutineTest&) =
delete;
~VideoConferencingRoutineTest() override = default;
void CompareVerdict(
mojom::RoutineVerdict expected_verdict,
const std::vector<mojom::VideoConferencingProblem>& expected_problems,
const base::Optional<std::string>& expected_support_details,
mojom::RoutineVerdict actual_verdict,
const std::vector<mojom::VideoConferencingProblem>& actual_problems,
const base::Optional<std::string>& actual_support_details) {
EXPECT_EQ(expected_verdict, actual_verdict);
EXPECT_EQ(expected_problems, actual_problems);
EXPECT_EQ(expected_support_details.has_value(),
actual_support_details.has_value());
if (expected_support_details.has_value() &&
actual_support_details.has_value()) {
EXPECT_EQ(expected_support_details.has_value(),
actual_support_details.has_value());
}
run_loop_.Quit();
}
std::unique_ptr<UdpProber> CreateAndExecuteUdpProber(
UdpProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
base::span<const uint8_t> data,
net::NetworkTrafficAnnotationTag tag,
base::TimeDelta timeout_after_host_resolution,
UdpProber::UdpProbeCompleteCallback callback) {
DCHECK(fake_udp_probe_results_.size() > 0);
auto value = fake_udp_probe_results_.front();
fake_udp_probe_results_.pop_front();
auto test_udp_prober = std::make_unique<TestUdpProber>(
std::move(callback), value.result, value.probe_exit_enum);
return std::move(test_udp_prober);
}
std::unique_ptr<TlsProber> CreateAndExecuteTlsProber(
TlsProber::NetworkContextGetter network_context_getter,
net::HostPortPair host_port_pair,
bool negotiate_tls,
TlsProber::TlsProbeCompleteCallback callback) {
DCHECK(fake_tls_probe_results_.size() > 0);
auto value = fake_tls_probe_results_.front();
fake_tls_probe_results_.pop_front();
auto test_tls_prober = std::make_unique<TestTlsProber>(
std::move(callback), value.result, value.probe_exit_enum);
return std::move(test_tls_prober);
}
protected:
void RunRoutine(
mojom::RoutineVerdict expected_routine_verdict,
const std::vector<mojom::VideoConferencingProblem>& expected_problems,
const base::Optional<std::string>& expected_support_details) {
video_conferencing_routine_->RunRoutine(base::BindOnce(
&VideoConferencingRoutineTest::CompareVerdict, weak_ptr(),
expected_routine_verdict, expected_problems, expected_support_details));
run_loop_.Run();
}
void SetUpRoutine(std::deque<UdpProberReturnValue> fake_udp_probe_results,
std::deque<TlsProberReturnValue> fake_tls_probe_results) {
fake_udp_probe_results_ = std::move(fake_udp_probe_results);
fake_tls_probe_results_ = std::move(fake_tls_probe_results);
video_conferencing_routine_ = std::make_unique<VideoConferencingRoutine>();
video_conferencing_routine_->set_udp_prober_getter_callback_for_testing(
base::BindRepeating(
&VideoConferencingRoutineTest::CreateAndExecuteUdpProber,
base::Unretained(this)));
video_conferencing_routine_->set_tls_prober_getter_callback_for_testing(
base::BindRepeating(
&VideoConferencingRoutineTest::CreateAndExecuteTlsProber,
base::Unretained(this)));
}
// Sets up required properties (via fakes) and runs the test.
//
// Parameters:
// |fake_udp_probe_results|: Represents the results of UDP probes.
// |fake_tls_probe_results|: Represents the results of TCP and TLS probes.
// |expected_routine_verdict|: Represents the expected verdict
// reported by this test.
// |expected_problems|: Represents the expected problem
// reported by this test.
void SetUpAndRunRoutine(
std::deque<UdpProberReturnValue> fake_udp_probe_results,
std::deque<TlsProberReturnValue> fake_tls_probe_results,
mojom::RoutineVerdict expected_routine_verdict,
const std::vector<mojom::VideoConferencingProblem>& expected_problems,
const base::Optional<std::string>& expected_support_details) {
SetUpRoutine(std::move(fake_udp_probe_results),
std::move(fake_tls_probe_results));
RunRoutine(expected_routine_verdict, expected_problems,
expected_support_details);
}
base::WeakPtr<VideoConferencingRoutineTest> weak_ptr() {
return weak_factory_.GetWeakPtr();
}
private:
content::BrowserTaskEnvironment task_environment_;
base::RunLoop run_loop_;
std::deque<UdpProberReturnValue> fake_udp_probe_results_;
std::deque<TlsProberReturnValue> fake_tls_probe_results_;
std::unique_ptr<VideoConferencingRoutine> video_conferencing_routine_;
base::WeakPtrFactory<VideoConferencingRoutineTest> weak_factory_{this};
};
// Tests the scenario where:
// (1) An open port to the STUN server is found via UDP and TCP.
// (2) All media hostnames are reachable.
TEST_F(VideoConferencingRoutineTest, TestSuccessfulPath) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
if (i < num_udp_ports_tested - 1) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
continue;
}
fake_udp_probe_results.push_back(
UdpProberReturnValue{net::OK, UdpProber::ProbeExitEnum::kSuccess});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
if (i < num_tcp_ports_tested - 1) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
continue;
}
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
// Results corresponding to the TLS requests to media hostnames.
int num_media_hostnames_tested = util::GetDefaultMediaUrls().size();
for (int i = 0; i < num_media_hostnames_tested; i++) {
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
SetUpAndRunRoutine(
std::move(fake_udp_probe_results), std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kNoProblem,
/*expected_problems=*/{}, /*expected_support_problems=*/base::nullopt);
}
// Tests the scenario where:
// (1) No open port to the STUN server is found via UDP.
TEST_F(VideoConferencingRoutineTest, TestUdpFailure) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
if (i < num_tcp_ports_tested - 1) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
continue;
}
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
// Results corresponding to the TLS requests to media hostnames.
int num_media_hostnames_tested = util::GetDefaultMediaUrls().size();
for (int i = 0; i < num_media_hostnames_tested; i++) {
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
SetUpAndRunRoutine(
std::move(fake_udp_probe_results), std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kProblem,
{mojom::VideoConferencingProblem::kUdpFailure}, kSupportDetails);
}
// Tests the scenario where:
// (1) No open port to the STUN server is found via TCP.
TEST_F(VideoConferencingRoutineTest, TestTcpFailure) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
if (i < num_udp_ports_tested - 1) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
continue;
}
fake_udp_probe_results.push_back(
UdpProberReturnValue{net::OK, UdpProber::ProbeExitEnum::kSuccess});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
}
// Results corresponding to the TLS requests to media hostnames.
int num_media_hostnames_tested = util::GetDefaultMediaUrls().size();
for (int i = 0; i < num_media_hostnames_tested; i++) {
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
SetUpAndRunRoutine(
std::move(fake_udp_probe_results), std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kProblem,
{mojom::VideoConferencingProblem::kTcpFailure}, kSupportDetails);
}
// Tests the scenario where:
// (1) Requests to one or more media hostnames failed.
TEST_F(VideoConferencingRoutineTest, TestMediaFailure) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
if (i < num_udp_ports_tested - 1) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
continue;
}
fake_udp_probe_results.push_back(
UdpProberReturnValue{net::OK, UdpProber::ProbeExitEnum::kSuccess});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
if (i < num_tcp_ports_tested - 1) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
continue;
}
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
// Results corresponding to the TLS requests to media hostnames.
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTlsUpgradeFailure});
SetUpAndRunRoutine(
std::move(fake_udp_probe_results), std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kProblem,
{mojom::VideoConferencingProblem::kMediaFailure}, kSupportDetails);
}
// Tests the scenario where:
// (1) No open port to the STUN server is found via UDP.
// (2) No open port to the STUN server is found via TCP.
TEST_F(VideoConferencingRoutineTest, TestUdpAndTcpFailure) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
}
// Results corresponding to the TLS requests to media hostnames.
int num_media_hostnames_tested = util::GetDefaultMediaUrls().size();
for (int i = 0; i < num_media_hostnames_tested; i++) {
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
SetUpAndRunRoutine(std::move(fake_udp_probe_results),
std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kProblem,
{mojom::VideoConferencingProblem::kUdpFailure,
mojom::VideoConferencingProblem::kTcpFailure},
kSupportDetails);
}
// Tests the scenario where:
// (1) No open port to the STUN server is found via UDP.
// (2) Requests to one or more media hostnames failed.
TEST_F(VideoConferencingRoutineTest, TestUdpAndMediaFailure) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
if (i < num_tcp_ports_tested - 1) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
continue;
}
fake_tls_probe_results.push_back(
TlsProberReturnValue{net::OK, TlsProber::ProbeExitEnum::kSuccess});
}
// Results corresponding to the TLS requests to media hostnames.
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTlsUpgradeFailure});
SetUpAndRunRoutine(std::move(fake_udp_probe_results),
std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kProblem,
{mojom::VideoConferencingProblem::kUdpFailure,
mojom::VideoConferencingProblem::kMediaFailure},
kSupportDetails);
}
// Tests the scenario where:
// (1) No open port to the STUN server is found via TCP.
// (2) Requests to one or more media hostnames failed.
TEST_F(VideoConferencingRoutineTest, TestTcpAndMediaFailure) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
if (i < num_udp_ports_tested - 1) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
continue;
}
fake_udp_probe_results.push_back(
UdpProberReturnValue{net::OK, UdpProber::ProbeExitEnum::kSuccess});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
}
// Results corresponding to the TLS requests to media hostnames.
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTlsUpgradeFailure});
SetUpAndRunRoutine(std::move(fake_udp_probe_results),
std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kProblem,
{mojom::VideoConferencingProblem::kTcpFailure,
mojom::VideoConferencingProblem::kMediaFailure},
kSupportDetails);
}
// Tests the scenario where:
// (1) No open port to the STUN server is found via UDP.
// (2) No open port to the STUN server is found via TCP.
// (3) Requests to one or more media hostnames failed.
TEST_F(VideoConferencingRoutineTest, TestTcpAndUdpAndMediaFailure) {
// Results corresponding to UDP requests to the STUN server.
int num_udp_ports_tested = util::GetUdpPortsForGoogleStunServer().size();
std::deque<UdpProberReturnValue> fake_udp_probe_results;
for (int i = 0; i < num_udp_ports_tested; i++) {
fake_udp_probe_results.push_back(UdpProberReturnValue{
net::ERR_FAILED, UdpProber::ProbeExitEnum::kNoDataReceivedFailure});
}
// Tracks the results corresponding to TCP requests to the STUN server and
// TLS requests to media hostnames.
std::deque<TlsProberReturnValue> fake_tls_probe_results;
// Results corresponding to the STUN server via TCP.
int num_tcp_ports_tested = util::GetTcpPortsForGoogleStunServer().size();
for (int i = 0; i < num_tcp_ports_tested; i++) {
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTcpConnectionFailure});
}
// Results corresponding to the TLS requests to media hostnames.
fake_tls_probe_results.push_back(TlsProberReturnValue{
net::ERR_FAILED, TlsProber::ProbeExitEnum::kTlsUpgradeFailure});
SetUpAndRunRoutine(std::move(fake_udp_probe_results),
std::move(fake_tls_probe_results),
mojom::RoutineVerdict::kProblem,
{mojom::VideoConferencingProblem::kUdpFailure,
mojom::VideoConferencingProblem::kTcpFailure,
mojom::VideoConferencingProblem::kMediaFailure},
kSupportDetails);
}
} // namespace network_diagnostics
} // namespace chromeos
......@@ -218,6 +218,11 @@ class MockNetworkDiagnosticsRoutines : public NetworkDiagnosticsRoutines {
HttpsLatency,
(NetworkDiagnosticsRoutines::HttpsLatencyCallback),
(override));
MOCK_METHOD(void,
VideoConferencing,
(const base::Optional<std::string>&,
NetworkDiagnosticsRoutines::VideoConferencingCallback),
(override));
mojo::PendingRemote<NetworkDiagnosticsRoutines> pending_remote() {
if (receiver_.is_bound()) {
......
......@@ -128,6 +128,17 @@ enum HttpsLatencyProblem {
kVeryHighLatency,
};
// Problems related to the VideoConferencing routine.
[Extensible]
enum VideoConferencingProblem {
// Failed requests to a STUN server via UDP.
kUdpFailure,
// Failed requests to a STUN server via TCP.
kTcpFailure,
// Failed to establish a TLS connection to media hostnames.
kMediaFailure,
};
// This interface is to be used by any clients that need to run specific
// network-related diagnostics. Expected clients of this interface are
// NetworkHealth, cros_healthd, and a connectivity diagnostics Web UI (to name
......@@ -180,4 +191,12 @@ interface NetworkDiagnosticsRoutines {
// the system.
HttpsLatency() => (RoutineVerdict verdict,
array<HttpsLatencyProblem> problems);
// Tests the device's video conferencing capabalities by testing whether the
// device can:
// (1) Contact either a default or specified STUN server via UDP.
// (2) Contact either a default or specified STUN server via TCP.
// (3) Reach common media endpoints.
VideoConferencing(string? stun_server_hostname) => (RoutineVerdict verdict,
array<VideoConferencingProblem> problems, string? support_details);
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment