getStats() promise never rejects nor resolves when peer connection state is closed.
https://bugs.webkit.org/show_bug.cgi?id=204842
<rdar://problem/57617107>

Reviewed by Eric Carlson.

Source/WebCore:

Instead of closing and nulling the backend when closing the peer connection,
we only close it. This allows calling getStats to retrieve the last gathered stats from the backend.
Covered by updated test.

* Modules/mediastream/PeerConnectionBackend.h:
* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::close):
(WebCore::RTCPeerConnection::stop):
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
(WebCore::LibWebRTCMediaEndpoint::close):
* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
(WebCore::LibWebRTCPeerConnectionBackend::close):
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:

LayoutTests:

* webrtc/video-stats-expected.txt:
* webrtc/video-stats.html:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@253146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index c650863..6fd02ec 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2019-12-05  youenn fablet  <youenn@apple.com>
+
+        getStats() promise never rejects nor resolves when peer connection state is closed.
+        https://bugs.webkit.org/show_bug.cgi?id=204842
+        <rdar://problem/57617107>
+
+        Reviewed by Eric Carlson.
+
+        * webrtc/video-stats-expected.txt:
+        * webrtc/video-stats.html:
+
 2019-12-04  Jack Lee  <shihchieh_lee@apple.com>
 
         Nullptr crash in RenderLayoutState::pageLogicalHeight const via RenderGrid::computeIntrinsicLogicalWidths inside RenderMarquee::updateMarqueePosition
diff --git a/LayoutTests/webrtc/video-stats-expected.txt b/LayoutTests/webrtc/video-stats-expected.txt
index 7b93920..7f5eb0a 100644
--- a/LayoutTests/webrtc/video-stats-expected.txt
+++ b/LayoutTests/webrtc/video-stats-expected.txt
@@ -3,4 +3,5 @@
 PASS Sender stats 
 PASS Receiver stats 
 PASS Check ssrc is not changing in inbound rtp stats 
+PASS Stats after pc close 
 
diff --git a/LayoutTests/webrtc/video-stats.html b/LayoutTests/webrtc/video-stats.html
index 9c3668d..d2b7c5a 100644
--- a/LayoutTests/webrtc/video-stats.html
+++ b/LayoutTests/webrtc/video-stats.html
@@ -187,6 +187,12 @@
     });
     assert_equals(instats1.ssrc, instats2.ssrc);
 }, "Check ssrc is not changing in inbound rtp stats");
+
+promise_test(async (test) => {
+    const pc = new RTCPeerConnection();
+    pc.close();
+    return pc.getStats();
+}, "Stats after pc close");
         </script>
     </body>
 </html>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 4936ab6..d7a9c5b 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,26 @@
+2019-12-05  youenn fablet  <youenn@apple.com>
+
+        getStats() promise never rejects nor resolves when peer connection state is closed.
+        https://bugs.webkit.org/show_bug.cgi?id=204842
+        <rdar://problem/57617107>
+
+        Reviewed by Eric Carlson.
+
+        Instead of closing and nulling the backend when closing the peer connection,
+        we only close it. This allows calling getStats to retrieve the last gathered stats from the backend.
+        Covered by updated test.
+
+        * Modules/mediastream/PeerConnectionBackend.h:
+        * Modules/mediastream/RTCPeerConnection.cpp:
+        (WebCore::RTCPeerConnection::close):
+        (WebCore::RTCPeerConnection::stop):
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
+        (WebCore::LibWebRTCMediaEndpoint::close):
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h:
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
+        (WebCore::LibWebRTCPeerConnectionBackend::close):
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
+
 2019-12-04  Ryosuke Niwa  <rniwa@webkit.org>
 
         Remove DocumentEventQueue and WorkerEventQueue
diff --git a/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h b/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h
index 9015ea2..e7879f4 100644
--- a/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h
+++ b/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h
@@ -99,6 +99,8 @@
 
     void stop();
 
+    virtual void close() = 0;
+
     virtual RefPtr<RTCSessionDescription> localDescription() const = 0;
     virtual RefPtr<RTCSessionDescription> currentLocalDescription() const = 0;
     virtual RefPtr<RTCSessionDescription> pendingLocalDescription() const = 0;
diff --git a/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp b/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
index 3ceeb43..05471f36 100644
--- a/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
+++ b/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
@@ -455,7 +455,7 @@
 
     updateConnectionState();
     ASSERT(isClosed());
-    doStop();
+    m_backend->close();
 }
 
 void RTCPeerConnection::emulatePlatformEvent(const String& action)
@@ -465,9 +465,7 @@
 
 void RTCPeerConnection::stop()
 {
-    if (!doClose())
-        return;
-
+    doClose();
     doStop();
 }
 
@@ -477,8 +475,8 @@
         return;
 
     m_isStopped = true;
-
-    m_backend->stop();
+    if (m_backend)
+        m_backend->stop();
 }
 
 void RTCPeerConnection::registerToController(RTCController& controller)
diff --git a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp
index 755e732..388731f 100644
--- a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp
+++ b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp
@@ -642,6 +642,12 @@
     });
 }
 
+void LibWebRTCMediaEndpoint::close()
+{
+    m_backend->Close();
+    stopLoggingStats();
+}
+
 void LibWebRTCMediaEndpoint::stop()
 {
     if (!m_backend)
diff --git a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h
index 41254c7..9af5c5a 100644
--- a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h
+++ b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.h
@@ -88,6 +88,7 @@
     std::unique_ptr<RTCDataChannelHandler> createDataChannel(const String&, const RTCDataChannelInit&);
     bool addIceCandidate(webrtc::IceCandidateInterface& candidate) { return m_backend->AddIceCandidate(&candidate); }
 
+    void close();
     void stop();
     bool isStopped() const { return !m_backend; }
 
diff --git a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp
index 85d216f..d254b39 100644
--- a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp
+++ b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp
@@ -251,6 +251,11 @@
     m_endpoint->doCreateAnswer();
 }
 
+void LibWebRTCPeerConnectionBackend::close()
+{
+    m_endpoint->close();
+}
+
 void LibWebRTCPeerConnectionBackend::doStop()
 {
     m_endpoint->stop();
diff --git a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h
index 8b32469..c706a2a 100644
--- a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h
+++ b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h
@@ -58,6 +58,7 @@
     void replaceTrack(RTCRtpSender&, RefPtr<MediaStreamTrack>&&, DOMPromiseDeferred<void>&&);
 
 private:
+    void close() final;
     void doCreateOffer(RTCOfferOptions&&) final;
     void doCreateAnswer(RTCAnswerOptions&&) final;
     void doSetLocalDescription(RTCSessionDescription&) final;