Title: [250582] trunk/Source/WebCore
Revision
250582
Author
you...@apple.com
Date
2019-10-01 14:35:38 -0700 (Tue, 01 Oct 2019)

Log Message

Queue events and promise resolution in RTCPeerConnection when suspended for page cache
https://bugs.webkit.org/show_bug.cgi?id=202396

Reviewed by Chris Dumez.

This patch prepares RTCPeerConnection to be suspendable to enter page cache.
For that purpose, we queue events and promise resolution/rejection tasks if the RTCPeerConnection m_shouldDelayTasks is set to true.
This queueing is enabled when RTCPeerConnection is asked to suspend itself.
The queued tasks are then executed at resume time.
Renamed fireEvent to dispatchEventWhenFeasible.
No change of behavior for now.

* Modules/mediastream/PeerConnectionBackend.cpp:
(WebCore::PeerConnectionBackend::createOfferSucceeded):
(WebCore::PeerConnectionBackend::createOfferFailed):
(WebCore::PeerConnectionBackend::createAnswerSucceeded):
(WebCore::PeerConnectionBackend::createAnswerFailed):
(WebCore::PeerConnectionBackend::setLocalDescriptionSucceeded):
(WebCore::PeerConnectionBackend::setLocalDescriptionFailed):
(WebCore::PeerConnectionBackend::setRemoteDescriptionSucceeded):
(WebCore::PeerConnectionBackend::setRemoteDescriptionFailed):
(WebCore::PeerConnectionBackend::addIceCandidateSucceeded):
(WebCore::PeerConnectionBackend::addIceCandidateFailed):
* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::doClose):
(WebCore::RTCPeerConnection::suspend):
(WebCore::RTCPeerConnection::resume):
(WebCore::RTCPeerConnection::updateIceGatheringState):
(WebCore::RTCPeerConnection::updateIceConnectionState):
(WebCore::RTCPeerConnection::updateConnectionState):
(WebCore::RTCPeerConnection::scheduleNegotiationNeededEvent):
(WebCore::RTCPeerConnection::doTask):
(WebCore::RTCPeerConnection::fireEvent):
* Modules/mediastream/RTCPeerConnection.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (250581 => 250582)


--- trunk/Source/WebCore/ChangeLog	2019-10-01 21:26:06 UTC (rev 250581)
+++ trunk/Source/WebCore/ChangeLog	2019-10-01 21:35:38 UTC (rev 250582)
@@ -1,3 +1,40 @@
+2019-10-01  youenn fablet  <you...@apple.com>
+
+        Queue events and promise resolution in RTCPeerConnection when suspended for page cache
+        https://bugs.webkit.org/show_bug.cgi?id=202396
+
+        Reviewed by Chris Dumez.
+
+        This patch prepares RTCPeerConnection to be suspendable to enter page cache.
+        For that purpose, we queue events and promise resolution/rejection tasks if the RTCPeerConnection m_shouldDelayTasks is set to true.
+        This queueing is enabled when RTCPeerConnection is asked to suspend itself.
+        The queued tasks are then executed at resume time.
+        Renamed fireEvent to dispatchEventWhenFeasible.
+        No change of behavior for now.
+
+        * Modules/mediastream/PeerConnectionBackend.cpp:
+        (WebCore::PeerConnectionBackend::createOfferSucceeded):
+        (WebCore::PeerConnectionBackend::createOfferFailed):
+        (WebCore::PeerConnectionBackend::createAnswerSucceeded):
+        (WebCore::PeerConnectionBackend::createAnswerFailed):
+        (WebCore::PeerConnectionBackend::setLocalDescriptionSucceeded):
+        (WebCore::PeerConnectionBackend::setLocalDescriptionFailed):
+        (WebCore::PeerConnectionBackend::setRemoteDescriptionSucceeded):
+        (WebCore::PeerConnectionBackend::setRemoteDescriptionFailed):
+        (WebCore::PeerConnectionBackend::addIceCandidateSucceeded):
+        (WebCore::PeerConnectionBackend::addIceCandidateFailed):
+        * Modules/mediastream/RTCPeerConnection.cpp:
+        (WebCore::RTCPeerConnection::doClose):
+        (WebCore::RTCPeerConnection::suspend):
+        (WebCore::RTCPeerConnection::resume):
+        (WebCore::RTCPeerConnection::updateIceGatheringState):
+        (WebCore::RTCPeerConnection::updateIceConnectionState):
+        (WebCore::RTCPeerConnection::updateConnectionState):
+        (WebCore::RTCPeerConnection::scheduleNegotiationNeededEvent):
+        (WebCore::RTCPeerConnection::doTask):
+        (WebCore::RTCPeerConnection::fireEvent):
+        * Modules/mediastream/RTCPeerConnection.h:
+
 2019-10-01  Brent Fulgham  <bfulg...@apple.com>
 
         [FTW] Correct additional canvas test failures

Modified: trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp (250581 => 250582)


--- trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp	2019-10-01 21:26:06 UTC (rev 250581)
+++ trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp	2019-10-01 21:35:38 UTC (rev 250582)
@@ -100,8 +100,9 @@
         return;
 
     ASSERT(m_offerAnswerPromise);
-    m_offerAnswerPromise->resolve(RTCSessionDescription::Init { RTCSdpType::Offer, filterSDP(WTFMove(sdp)) });
-    m_offerAnswerPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_offerAnswerPromise), sdp = filterSDP(WTFMove(sdp))]() mutable {
+        promise->resolve(RTCSessionDescription::Init { RTCSdpType::Offer, sdp });
+    });
 }
 
 void PeerConnectionBackend::createOfferFailed(Exception&& exception)
@@ -113,8 +114,9 @@
         return;
 
     ASSERT(m_offerAnswerPromise);
-    m_offerAnswerPromise->reject(WTFMove(exception));
-    m_offerAnswerPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_offerAnswerPromise), exception = WTFMove(exception)]() mutable {
+        promise->reject(WTFMove(exception));
+    });
 }
 
 void PeerConnectionBackend::createAnswer(RTCAnswerOptions&& options, PeerConnection::SessionDescriptionPromise&& promise)
@@ -135,8 +137,9 @@
         return;
 
     ASSERT(m_offerAnswerPromise);
-    m_offerAnswerPromise->resolve(RTCSessionDescription::Init { RTCSdpType::Answer, WTFMove(sdp) });
-    m_offerAnswerPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_offerAnswerPromise), sdp = WTFMove(sdp)]() mutable {
+        promise->resolve(RTCSessionDescription::Init { RTCSdpType::Answer, sdp });
+    });
 }
 
 void PeerConnectionBackend::createAnswerFailed(Exception&& exception)
@@ -148,8 +151,9 @@
         return;
 
     ASSERT(m_offerAnswerPromise);
-    m_offerAnswerPromise->reject(WTFMove(exception));
-    m_offerAnswerPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_offerAnswerPromise), exception = WTFMove(exception)]() mutable {
+        promise->reject(WTFMove(exception));
+    });
 }
 
 static inline bool isLocalDescriptionTypeValidForState(RTCSdpType type, RTCSignalingState state)
@@ -192,10 +196,11 @@
     if (m_peerConnection.isClosed())
         return;
 
+
     ASSERT(m_setDescriptionPromise);
-
-    m_setDescriptionPromise->resolve();
-    m_setDescriptionPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_setDescriptionPromise)]() mutable {
+        promise->resolve();
+    });
 }
 
 void PeerConnectionBackend::setLocalDescriptionFailed(Exception&& exception)
@@ -207,9 +212,9 @@
         return;
 
     ASSERT(m_setDescriptionPromise);
-
-    m_setDescriptionPromise->reject(WTFMove(exception));
-    m_setDescriptionPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_setDescriptionPromise), exception = WTFMove(exception)]() mutable {
+        promise->reject(WTFMove(exception));
+    });
 }
 
 static inline bool isRemoteDescriptionTypeValidForState(RTCSdpType type, RTCSignalingState state)
@@ -255,7 +260,7 @@
     for (auto& event : events) {
         auto& track = event.track.get();
 
-        m_peerConnection.fireEvent(RTCTrackEvent::create(eventNames().trackEvent, Event::CanBubble::No, Event::IsCancelable::No, WTFMove(event.receiver), WTFMove(event.track), WTFMove(event.streams), WTFMove(event.transceiver)));
+        m_peerConnection.dispatchEventWhenFeasible(RTCTrackEvent::create(eventNames().trackEvent, Event::CanBubble::No, Event::IsCancelable::No, WTFMove(event.receiver), WTFMove(event.track), WTFMove(event.streams), WTFMove(event.transceiver)));
 
         if (m_peerConnection.isClosed())
             return;
@@ -267,10 +272,11 @@
     if (m_peerConnection.isClosed())
         return;
 
+
     ASSERT(m_setDescriptionPromise);
-
-    m_setDescriptionPromise->resolve();
-    m_setDescriptionPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_setDescriptionPromise)]() mutable {
+        promise->resolve();
+    });
 }
 
 void PeerConnectionBackend::setRemoteDescriptionFailed(Exception&& exception)
@@ -283,9 +289,9 @@
 
     ASSERT(!m_peerConnection.isClosed());
     ASSERT(m_setDescriptionPromise);
-
-    m_setDescriptionPromise->reject(WTFMove(exception));
-    m_setDescriptionPromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_setDescriptionPromise), exception = WTFMove(exception)]() mutable {
+        promise->reject(WTFMove(exception));
+    });
 }
 
 void PeerConnectionBackend::addPendingTrackEvent(PendingTrackEvent&& event)
@@ -332,9 +338,9 @@
         return;
 
     ASSERT(m_addIceCandidatePromise);
-
-    m_addIceCandidatePromise->resolve();
-    m_addIceCandidatePromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_addIceCandidatePromise)]() mutable {
+        promise->resolve();
+    });
 }
 
 void PeerConnectionBackend::addIceCandidateFailed(Exception&& exception)
@@ -346,9 +352,9 @@
         return;
 
     ASSERT(m_addIceCandidatePromise);
-
-    m_addIceCandidatePromise->reject(WTFMove(exception));
-    m_addIceCandidatePromise = WTF::nullopt;
+    m_peerConnection.doTask([promise = WTFMove(m_addIceCandidatePromise), exception = WTFMove(exception)]() mutable {
+        promise->reject(WTFMove(exception));
+    });
 }
 
 void PeerConnectionBackend::fireICECandidateEvent(RefPtr<RTCIceCandidate>&& candidate, String&& serverURL)
@@ -355,7 +361,7 @@
 {
     ASSERT(isMainThread());
 
-    m_peerConnection.fireEvent(RTCPeerConnectionIceEvent::create(Event::CanBubble::No, Event::IsCancelable::No, WTFMove(candidate), WTFMove(serverURL)));
+    m_peerConnection.dispatchEventWhenFeasible(RTCPeerConnectionIceEvent::create(Event::CanBubble::No, Event::IsCancelable::No, WTFMove(candidate), WTFMove(serverURL)));
 }
 
 void PeerConnectionBackend::enableICECandidateFiltering()
@@ -459,7 +465,7 @@
     if (m_waitingForMDNSRegistration)
         return;
 
-    m_peerConnection.fireEvent(RTCPeerConnectionIceEvent::create(Event::CanBubble::No, Event::IsCancelable::No, nullptr, { }));
+    m_peerConnection.dispatchEventWhenFeasible(RTCPeerConnectionIceEvent::create(Event::CanBubble::No, Event::IsCancelable::No, nullptr, { }));
     m_peerConnection.updateIceGatheringState(RTCIceGatheringState::Complete);
     m_pendingICECandidates.clear();
 }
@@ -508,7 +514,7 @@
 
     if (newSignalingState != m_peerConnection.signalingState()) {
         m_peerConnection.setSignalingState(newSignalingState);
-        m_peerConnection.fireEvent(Event::create(eventNames().signalingstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
+        m_peerConnection.dispatchEventWhenFeasible(Event::create(eventNames().signalingstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
     }
 }
 

Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp (250581 => 250582)


--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp	2019-10-01 21:26:06 UTC (rev 250581)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp	2019-10-01 21:35:38 UTC (rev 250582)
@@ -433,6 +433,7 @@
     if (isClosed())
         return false;
 
+    m_shouldDelayTasks = false;
     m_connectionState = RTCPeerConnectionState::Closed;
     m_iceConnectionState = RTCIceConnectionState::Closed;
     m_signalingState = RTCSignalingState::Closed;
@@ -496,12 +497,36 @@
     return "RTCPeerConnection";
 }
 
-    // FIXME: We should do better here, it is way too easy to prevent PageCache.
+// FIXME: We should do better here, it is way too easy to prevent PageCache.
 bool RTCPeerConnection::canSuspendForDocumentSuspension() const
 {
     return !hasPendingActivity();
 }
 
+void RTCPeerConnection::suspend(ReasonForSuspension reason)
+{
+    if (reason != ReasonForSuspension::PageCache)
+        return;
+
+    m_shouldDelayTasks = true;
+}
+
+void RTCPeerConnection::resume()
+{
+    if (!m_shouldDelayTasks)
+        return;
+
+    m_shouldDelayTasks = false;
+    scriptExecutionContext()->postTask([this, protectedThis = makeRef(*this)](auto&) {
+        if (m_isStopped || m_shouldDelayTasks)
+            return;
+
+        auto tasks = WTFMove(m_pendingTasks);
+        for (auto& task : tasks)
+            task();
+    });
+}
+
 bool RTCPeerConnection::hasPendingActivity() const
 {
     if (m_isStopped)
@@ -536,7 +561,7 @@
             return;
 
         protectedThis->m_iceGatheringState = newState;
-        protectedThis->dispatchEvent(Event::create(eventNames().icegatheringstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
+        protectedThis->dispatchEventWhenFeasible(Event::create(eventNames().icegatheringstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
         protectedThis->updateConnectionState();
     });
 }
@@ -550,7 +575,7 @@
             return;
 
         protectedThis->m_iceConnectionState = newState;
-        protectedThis->dispatchEvent(Event::create(eventNames().iceconnectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
+        protectedThis->dispatchEventWhenFeasible(Event::create(eventNames().iceconnectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
         protectedThis->updateConnectionState();
     });
 }
@@ -580,7 +605,7 @@
     INFO_LOG(LOGIDENTIFIER, "state changed from: " , m_connectionState, " to ", state);
 
     m_connectionState = state;
-    dispatchEvent(Event::create(eventNames().connectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
+    dispatchEventWhenFeasible(Event::create(eventNames().connectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
 }
 
 void RTCPeerConnection::scheduleNegotiationNeededEvent()
@@ -591,15 +616,26 @@
         if (!protectedThis->m_backend->isNegotiationNeeded())
             return;
         protectedThis->m_backend->clearNegotiationNeededState();
-        protectedThis->dispatchEvent(Event::create(eventNames().negotiationneededEvent, Event::CanBubble::No, Event::IsCancelable::No));
+        protectedThis->dispatchEventWhenFeasible(Event::create(eventNames().negotiationneededEvent, Event::CanBubble::No, Event::IsCancelable::No));
     });
 }
 
-void RTCPeerConnection::fireEvent(Event& event)
+void RTCPeerConnection::doTask(Function<void()>&& task)
 {
-    dispatchEvent(event);
+    if (m_shouldDelayTasks || !m_pendingTasks.isEmpty()) {
+        m_pendingTasks.append(WTFMove(task));
+        return;
+    }
+    task();
 }
 
+void RTCPeerConnection::dispatchEventWhenFeasible(Ref<Event>&& event)
+{
+    doTask([this, event = WTFMove(event)] {
+        dispatchEvent(event);
+    });
+}
+
 void RTCPeerConnection::dispatchEvent(Event& event)
 {
     INFO_LOG(LOGIDENTIFIER, "dispatching '", event.type(), "'");

Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h (250581 => 250582)


--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h	2019-10-01 21:26:06 UTC (rev 250581)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h	2019-10-01 21:35:38 UTC (rev 250582)
@@ -165,7 +165,7 @@
 
     void scheduleNegotiationNeededEvent();
 
-    void fireEvent(Event&);
+    void dispatchEventWhenFeasible(Ref<Event>&&);
 
     void disableICECandidateFiltering() { m_backend->disableICECandidateFiltering(); }
     void enableICECandidateFiltering() { m_backend->enableICECandidateFiltering(); }
@@ -177,6 +177,8 @@
     
     Document* document();
 
+    void doTask(Function<void()>&&);
+
 #if !RELEASE_LOG_DISABLED
     const Logger& logger() const final { return m_logger.get(); }
     const void* logIdentifier() const final { return m_logIdentifier; }
@@ -210,6 +212,8 @@
     WEBCORE_EXPORT void stop() final;
     const char* activeDOMObjectName() const final;
     bool canSuspendForDocumentSuspension() const final;
+    void suspend(ReasonForSuspension) final;
+    void resume() final;
 
     void updateConnectionState();
     bool doClose();
@@ -235,6 +239,8 @@
     RTCConfiguration m_configuration;
     RTCController* m_controller { nullptr };
     Vector<RefPtr<RTCCertificate>> m_certificates;
+    bool m_shouldDelayTasks { false };
+    Vector<Function<void()>> m_pendingTasks;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp (250581 => 250582)


--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp	2019-10-01 21:26:06 UTC (rev 250581)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp	2019-10-01 21:35:38 UTC (rev 250582)
@@ -663,7 +663,7 @@
         if (protectedThis->isStopped())
             return;
         auto& connection = protectedThis->m_peerConnectionBackend.connection();
-        connection.fireEvent(LibWebRTCDataChannelHandler::channelEvent(*connection.document(), WTFMove(dataChannel)));
+        connection.dispatchEventWhenFeasible(LibWebRTCDataChannelHandler::channelEvent(*connection.document(), WTFMove(dataChannel)));
     });
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to