Add support for IceCandidate stats
authoryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Oct 2018 15:44:34 +0000 (15:44 +0000)
committeryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Oct 2018 15:44:34 +0000 (15:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190329

Reviewed by Eric Carlson.

Source/ThirdParty/libwebrtc:

Export new stats kType values.

* Configurations/libwebrtc.iOS.exp:
* Configurations/libwebrtc.iOSsim.exp:
* Configurations/libwebrtc.mac.exp:

Source/WebCore:

Convert IceCandidate stats gathered by libwebrtc.
Since networkType might be sensitive information, we currently do not expose it.
We do not expose address either if it is a host or prflx candidate.

Test: webrtc/candidate-stats.html

* Modules/mediastream/RTCStatsReport.h:
* Modules/mediastream/RTCStatsReport.idl:
* Modules/mediastream/libwebrtc/LibWebRTCStatsCollector.cpp:
(WebCore::iceCandidateState):
(WebCore::fillRTCIceCandidateStats):
(WebCore::LibWebRTCStatsCollector::OnStatsDelivered):

LayoutTests:

* webrtc/candidate-stats-expected.txt: Added.
* webrtc/candidate-stats.html: Added.
* webrtc/routines.js:
* webrtc/video-stats.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@236963 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/webrtc/candidate-stats-expected.txt [new file with mode: 0644]
LayoutTests/webrtc/candidate-stats.html [new file with mode: 0644]
LayoutTests/webrtc/routines.js
LayoutTests/webrtc/video-stats.html
Source/ThirdParty/libwebrtc/ChangeLog
Source/ThirdParty/libwebrtc/Configurations/libwebrtc.iOS.exp
Source/ThirdParty/libwebrtc/Configurations/libwebrtc.iOSsim.exp
Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediastream/RTCStatsReport.h
Source/WebCore/Modules/mediastream/RTCStatsReport.idl
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCStatsCollector.cpp

index 5112c54..86ef4fd 100644 (file)
@@ -1,3 +1,15 @@
+2018-10-09  Youenn Fablet  <youenn@apple.com>
+
+        Add support for IceCandidate stats
+        https://bugs.webkit.org/show_bug.cgi?id=190329
+
+        Reviewed by Eric Carlson.
+
+        * webrtc/candidate-stats-expected.txt: Added.
+        * webrtc/candidate-stats.html: Added.
+        * webrtc/routines.js:
+        * webrtc/video-stats.html:
+
 2018-10-09  Philippe Normand  <pnormand@igalia.com>
 
         [GStreamer] Stealing cross-origin video pixel with HLS
diff --git a/LayoutTests/webrtc/candidate-stats-expected.txt b/LayoutTests/webrtc/candidate-stats-expected.txt
new file mode 100644 (file)
index 0000000..23fe684
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS ICE candidate data channel stats 
+
diff --git a/LayoutTests/webrtc/candidate-stats.html b/LayoutTests/webrtc/candidate-stats.html
new file mode 100644 (file)
index 0000000..eadf738
--- /dev/null
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Testing basic video exchange from offerer to receiver</title>
+        <script src="../resources/testharness.js"></script>
+        <script src="../resources/testharnessreport.js"></script>
+    </head>
+    <body>
+        <script src ="routines.js"></script>
+        <script>
+promise_test(async (test) => {
+    let firstConnection, secondConnection;
+    await new Promise((resolve, reject) => {
+        createConnections((connection) => {
+            firstConnection = connection;
+            localChannel = connection.createDataChannel('sendDataChannel');
+        }, (connection) => {
+            secondConnection = connection;
+            connection.ondatachannel = resolve;
+        });
+        setTimeout(() => { reject("Test timed out"); }, 5000);
+    });
+
+    let stats = await getTypedStats(firstConnection, "local-candidate");
+    assert_true(!stats.address, "address is not exposed");
+    assert_true(!stats.networkType, "networkType is not exposed");
+
+    assert_array_equals(Object.keys(stats), ["id","timestamp","type","candidateType","deleted","port","priority","protocol","transportId"], "local");
+
+    stats = await getTypedStats(firstConnection, "remote-candidate");
+
+    // For now, we do not want to expose address or networkType.
+    assert_true(!stats.address, "address is not exposed");
+    assert_true(!stats.networkType, "networkType is not exposed");
+
+    assert_array_equals(Object.keys(stats), ["id","timestamp","type","candidateType","deleted","port","priority","protocol","transportId"], "remote");
+}, "ICE candidate data channel stats");
+        </script>
+    </body>
+</html>
index c9de505..d3b1a0e 100644 (file)
@@ -211,3 +211,14 @@ function setCodec(sdp, codec)
         return line.indexOf('a=fmtp') === -1 && line.indexOf('a=rtcp-fb') === -1 && (line.indexOf('a=rtpmap') === -1 || line.indexOf(codec) !== -1);
     }).join('\r\n');
 }
+
+async function getTypedStats(connection, type)
+{
+    const report = await connection.getStats();
+    var stats;
+    report.forEach((statItem) => {
+        if (statItem.type === type)
+            stats = statItem;
+    });
+    return stats;
+}
index dc1c4a5..34abcbc 100644 (file)
@@ -137,10 +137,10 @@ promise_test(async (test) => {
     await checkOutboundFramesNumberIncreased(firstConnection, statsFirstConnection, 0);
 
     let types = await getStatsType(firstConnection);
-    assert_array_equals(types, ["candidate-pair", "certificate", "codec", "inbound-rtp", "outbound-rtp", "track"]);
+    assert_array_equals(types, ["candidate-pair", "certificate", "codec", "inbound-rtp", "local-candidate", "outbound-rtp", "remote-candidate", "track"]);
 
     types = await getStatsType(secondConnection);
-    assert_array_equals(types, ["candidate-pair", "certificate", "codec", "inbound-rtp", "outbound-rtp", "track"]);
+    assert_array_equals(types, ["candidate-pair", "certificate", "codec", "inbound-rtp", "local-candidate", "outbound-rtp", "remote-candidate", "track"]);
 }, "Basic video stats");
 
 promise_test(async (test) => {
index 4092d74..e74fad5 100644 (file)
@@ -1,3 +1,16 @@
+2018-10-09  Youenn Fablet  <youenn@apple.com>
+
+        Add support for IceCandidate stats
+        https://bugs.webkit.org/show_bug.cgi?id=190329
+
+        Reviewed by Eric Carlson.
+
+        Export new stats kType values.
+
+        * Configurations/libwebrtc.iOS.exp:
+        * Configurations/libwebrtc.iOSsim.exp:
+        * Configurations/libwebrtc.mac.exp:
+
 2018-10-06  Dan Bernstein  <mitz@apple.com>
 
         [Xcode] Never build yasm with ASAN
index 146eeba..cf52d31 100644 (file)
@@ -216,3 +216,5 @@ __ZN6webrtc18RtpTransceiverInitC1Ev
 __ZN6webrtc18RtpTransceiverInitD1Ev
 __ZN6webrtc9RtpSourceD1Ev
 __ZN6webrtc11field_trial25InitFieldTrialsFromStringEPKc
+__ZN6webrtc25RTCLocalIceCandidateStats5kTypeE
+__ZN6webrtc26RTCRemoteIceCandidateStats5kTypeE
index 03de261..16e6cab 100644 (file)
@@ -217,3 +217,5 @@ __ZN6webrtc18RtpTransceiverInitC1Ev
 __ZN6webrtc18RtpTransceiverInitD1Ev
 __ZN6webrtc9RtpSourceD1Ev
 __ZN6webrtc11field_trial25InitFieldTrialsFromStringEPKc
+__ZN6webrtc25RTCLocalIceCandidateStats5kTypeE
+__ZN6webrtc26RTCRemoteIceCandidateStats5kTypeE
index 03de261..16e6cab 100644 (file)
@@ -217,3 +217,5 @@ __ZN6webrtc18RtpTransceiverInitC1Ev
 __ZN6webrtc18RtpTransceiverInitD1Ev
 __ZN6webrtc9RtpSourceD1Ev
 __ZN6webrtc11field_trial25InitFieldTrialsFromStringEPKc
+__ZN6webrtc25RTCLocalIceCandidateStats5kTypeE
+__ZN6webrtc26RTCRemoteIceCandidateStats5kTypeE
index 651fb8e..0b2e424 100644 (file)
@@ -1,3 +1,23 @@
+2018-10-09  Youenn Fablet  <youenn@apple.com>
+
+        Add support for IceCandidate stats
+        https://bugs.webkit.org/show_bug.cgi?id=190329
+
+        Reviewed by Eric Carlson.
+
+        Convert IceCandidate stats gathered by libwebrtc.
+        Since networkType might be sensitive information, we currently do not expose it.
+        We do not expose address either if it is a host or prflx candidate.
+
+        Test: webrtc/candidate-stats.html
+
+        * Modules/mediastream/RTCStatsReport.h:
+        * Modules/mediastream/RTCStatsReport.idl:
+        * Modules/mediastream/libwebrtc/LibWebRTCStatsCollector.cpp:
+        (WebCore::iceCandidateState):
+        (WebCore::fillRTCIceCandidateStats):
+        (WebCore::LibWebRTCStatsCollector::OnStatsDelivered):
+
 2018-10-09  Philippe Normand  <pnormand@igalia.com>
 
         [GStreamer] Stealing cross-origin video pixel with HLS
index bac5831..cd27587 100644 (file)
@@ -177,6 +177,19 @@ public:
         unsigned long long consentResponsesSent { 0 };
     };
 
+    enum class IceCandidateType { Host, Srflx, Prflx, Relay };
+
+    struct IceCandidateStats : Stats {
+        String transportId;
+        String address;
+        std::optional<int32_t> port;
+        String protocol;
+        std::optional<IceCandidateType> candidateType;
+        std::optional<int32_t> priority;
+        String url;
+        bool deleted { false };
+    };
+
     struct CertificateStats : Stats {
         CertificateStats() { type = RTCStatsReport::Type::Certificate; }
 
index 0e7d333..c2f2d8d 100644 (file)
@@ -165,6 +165,27 @@ dictionary RTCIceCandidatePairStats : RTCStats {
     // FIXME: Expose other fields once libwebrtc support them.
 };
 
+enum RTCIceCandidateType {
+    "host",
+    "srflx",
+    "prflx",
+    "relay"
+};
+
+[ JSGenerateToJSObject ]
+dictionary RTCIceCandidateStats : RTCStats {
+    DOMString transportId;
+    // FIXME: decide whether to expose networkType
+    // FIXME: Expose relayProtocol
+    DOMString address;
+    long port;
+    DOMString protocol;
+    RTCIceCandidateType candidateType;
+    long priority;
+    DOMString url;
+    boolean deleted = false;
+};
+
 [ JSGenerateToJSObject ]
 dictionary RTCCertificateStats : RTCStats {
     DOMString fingerprint;
@@ -194,4 +215,3 @@ dictionary RTCCodecStats : RTCStats {
 // FIXME 169662: missing RTCMediaStreamStats
 // FIXME 169662: missing RTCTransportStats
 // FIXME 169662: missing RTCIceCandidateStats
-// FIXME 169662: missing RTCStatsIceCandidatePairState
index 298b1e3..278d40f 100644 (file)
@@ -278,6 +278,51 @@ static inline void fillRTCIceCandidatePairStats(RTCStatsReport::IceCandidatePair
         stats.consentResponsesSent = *rtcStats.responses_sent;
 }
 
+static inline std::optional<RTCStatsReport::IceCandidateType> iceCandidateState(const std::string& state)
+{
+    if (state == "host")
+        return RTCStatsReport::IceCandidateType::Host;
+    if (state == "srflx")
+        return RTCStatsReport::IceCandidateType::Srflx;
+    if (state == "prflx")
+        return RTCStatsReport::IceCandidateType::Prflx;
+    if (state == "relay")
+        return RTCStatsReport::IceCandidateType::Relay;
+
+    return { };
+}
+
+static inline void fillRTCIceCandidateStats(RTCStatsReport::IceCandidateStats& stats, const webrtc::RTCIceCandidateStats& rtcStats)
+{
+    stats.type = rtcStats.type() == webrtc::RTCRemoteIceCandidateStats::kType ? RTCStatsReport::Type::RemoteCandidate : RTCStatsReport::Type::LocalCandidate;
+
+    fillRTCStats(stats, rtcStats);
+
+    if (rtcStats.transport_id.is_defined())
+        stats.transportId = fromStdString(*rtcStats.transport_id);
+    if (rtcStats.ip.is_defined())
+        stats.address = fromStdString(*rtcStats.ip);
+    if (rtcStats.port.is_defined())
+        stats.port = *rtcStats.port;
+    if (rtcStats.protocol.is_defined())
+        stats.protocol = fromStdString(*rtcStats.protocol);
+
+    if (rtcStats.candidate_type.is_defined())
+        stats.candidateType = iceCandidateState(*rtcStats.candidate_type);
+
+    if (stats.candidateType == RTCStatsReport::IceCandidateType::Prflx)
+        stats.candidateType = { };
+    if (stats.candidateType == RTCStatsReport::IceCandidateType::Prflx || stats.candidateType == RTCStatsReport::IceCandidateType::Host)
+        stats.address = { };
+
+    if (rtcStats.priority.is_defined())
+        stats.priority = *rtcStats.priority;
+    if (rtcStats.url.is_defined())
+        stats.url = fromStdString(*rtcStats.url);
+    if (rtcStats.deleted.is_defined())
+        stats.deleted = *rtcStats.deleted;
+}
+
 static inline void fillRTCCertificateStats(RTCStatsReport::CertificateStats& stats, const webrtc::RTCCertificateStats& rtcStats)
 {
     fillRTCStats(stats, rtcStats);
@@ -340,6 +385,10 @@ void LibWebRTCStatsCollector::OnStatsDelivered(const rtc::scoped_refptr<const we
                 RTCStatsReport::IceCandidatePairStats stats;
                 fillRTCIceCandidatePairStats(stats, static_cast<const webrtc::RTCIceCandidatePairStats&>(rtcStats));
                 report->addStats<IDLDictionary<RTCStatsReport::IceCandidatePairStats>>(WTFMove(stats));
+            } else if (rtcStats.type() == webrtc::RTCRemoteIceCandidateStats::kType || rtcStats.type() == webrtc::RTCLocalIceCandidateStats::kType) {
+                RTCStatsReport::IceCandidateStats stats;
+                fillRTCIceCandidateStats(stats, static_cast<const webrtc::RTCIceCandidateStats&>(rtcStats));
+                report->addStats<IDLDictionary<RTCStatsReport::IceCandidateStats>>(WTFMove(stats));
             } else if (rtcStats.type() == webrtc::RTCCertificateStats::kType) {
                 RTCStatsReport::CertificateStats stats;
                 fillRTCCertificateStats(stats, static_cast<const webrtc::RTCCertificateStats&>(rtcStats));