[Cocoa] Media elements will restart network buffering just before suspending
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Feb 2019 00:21:47 +0000 (00:21 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Feb 2019 00:21:47 +0000 (00:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=193691

Reviewed by Eric Carlson.

Source/WebCore:

API Test: WebKit.ProcessSuspendMediaBuffering

Allow the Page to suspend all media buffering in its child Documents.

* dom/Document.cpp:
(WebCore::Document::suspendAllMediaBuffering):
(WebCore::Document::resumeAllMediaBuffering):
* dom/Document.h:
* html/MediaElementSession.cpp:
(WebCore::MediaElementSession::dataBufferingPermitted const):
(WebCore::MediaElementSession::suspendBuffering):
(WebCore::MediaElementSession::resumeBuffering):
(WebCore::MediaElementSession::bufferingSuspended const):
* html/MediaElementSession.h:
* page/Page.cpp:
(WebCore::Page::suspendAllMediaBuffering):
(WebCore::Page::resumeAllMediaBuffering):
* page/Page.h:
(WebCore::Page::mediaPlaybackIsSuspended const):
(WebCore::Page::mediaBufferingIsSuspended const):
(WebCore::Page::mediaPlaybackIsSuspended): Deleted.
* platform/audio/PlatformMediaSession.h:
(WebCore::PlatformMediaSession::suspendBuffering):
(WebCore::PlatformMediaSession::resumeBuffering):
* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::suspendAllMediaBufferingForDocument):
(WebCore::PlatformMediaSessionManager::resumeAllMediaBufferingForDocument):
* platform/audio/PlatformMediaSessionManager.h:

Source/WebKit:

When the WebProcess receives a notification that the process is about to become
suspended, it tells the MemoryPressureHandler to release all critical memory. This
has the side effect of causing AVFoundation-backed media elements to dump their
in-memory caches and start downloading media data again. Instead, media elements
should all stop buffering media data during suspension. Add new testing SPI to
simulate suspension and resume messages.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _processWillSuspendImminentlyForTesting]):
(-[WKWebView _processDidResumeForTesting]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebProcessProxy.h:
* UIProcess/ios/WKInkPickerView.mm:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::suspendAllMediaBuffering):
(WebKit::WebPage::resumeAllMediaBuffering):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::actualPrepareToSuspend):
(WebKit::WebProcess::cancelPrepareToSuspend):
(WebKit::WebProcess::processDidResume):
(WebKit::WebProcess::suspendAllMediaBuffering):
(WebKit::WebProcess::resumeAllMediaBuffering):
* WebProcess/WebProcess.h:

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/ProcessSuspendMediaBuffering.mm: Added.
(TEST):

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

21 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/MediaElementSession.cpp
Source/WebCore/html/MediaElementSession.h
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/platform/audio/PlatformMediaSession.h
Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp
Source/WebCore/platform/audio/PlatformMediaSessionManager.h
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebProcess.cpp
Source/WebKit/WebProcess/WebProcess.h
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSuspendMediaBuffering.mm [new file with mode: 0644]

index 15e1274..236590a 100644 (file)
@@ -1,5 +1,41 @@
 2019-02-13  Jer Noble  <jer.noble@apple.com>
 
+        [Cocoa] Media elements will restart network buffering just before suspending
+        https://bugs.webkit.org/show_bug.cgi?id=193691
+
+        Reviewed by Eric Carlson.
+
+        API Test: WebKit.ProcessSuspendMediaBuffering
+
+        Allow the Page to suspend all media buffering in its child Documents.
+
+        * dom/Document.cpp:
+        (WebCore::Document::suspendAllMediaBuffering):
+        (WebCore::Document::resumeAllMediaBuffering):
+        * dom/Document.h:
+        * html/MediaElementSession.cpp:
+        (WebCore::MediaElementSession::dataBufferingPermitted const):
+        (WebCore::MediaElementSession::suspendBuffering):
+        (WebCore::MediaElementSession::resumeBuffering):
+        (WebCore::MediaElementSession::bufferingSuspended const):
+        * html/MediaElementSession.h:
+        * page/Page.cpp:
+        (WebCore::Page::suspendAllMediaBuffering):
+        (WebCore::Page::resumeAllMediaBuffering):
+        * page/Page.h:
+        (WebCore::Page::mediaPlaybackIsSuspended const):
+        (WebCore::Page::mediaBufferingIsSuspended const):
+        (WebCore::Page::mediaPlaybackIsSuspended): Deleted.
+        * platform/audio/PlatformMediaSession.h:
+        (WebCore::PlatformMediaSession::suspendBuffering):
+        (WebCore::PlatformMediaSession::resumeBuffering):
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::suspendAllMediaBufferingForDocument):
+        (WebCore::PlatformMediaSessionManager::resumeAllMediaBufferingForDocument):
+        * platform/audio/PlatformMediaSessionManager.h:
+
+2019-02-13  Jer Noble  <jer.noble@apple.com>
+
         Entering fullscreen inside a shadow root will not set fullscreen pseudoclasses outside of root
         https://bugs.webkit.org/show_bug.cgi?id=194516
         <rdar://problem/44678353>
index 050555b..466becb 100644 (file)
@@ -1738,6 +1738,18 @@ void Document::resumeAllMediaPlayback()
     if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
         platformMediaSessionManager->resumeAllMediaPlaybackForDocument(*this);
 }
+
+void Document::suspendAllMediaBuffering()
+{
+    if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
+        platformMediaSessionManager->suspendAllMediaBufferingForDocument(*this);
+}
+
+void Document::resumeAllMediaBuffering()
+{
+    if (auto* platformMediaSessionManager = PlatformMediaSessionManager::sharedManagerIfExists())
+        platformMediaSessionManager->resumeAllMediaBufferingForDocument(*this);
+}
 #endif
 
 String Document::nodeName() const
index db8988d..d0314ab 100644 (file)
@@ -1126,6 +1126,8 @@ public:
     void stopAllMediaPlayback();
     void suspendAllMediaPlayback();
     void resumeAllMediaPlayback();
+    void suspendAllMediaBuffering();
+    void resumeAllMediaBuffering();
 #endif
 
     WEBCORE_EXPORT void setShouldCreateRenderers(bool);
index 71ac995..153415a 100644 (file)
@@ -379,6 +379,9 @@ bool MediaElementSession::dataBufferingPermitted() const
     if (isSuspended())
         return false;
 
+    if (bufferingSuspended())
+        return false;
+
     if (state() == PlatformMediaSession::Playing)
         return true;
 
@@ -785,6 +788,23 @@ void MediaElementSession::resetPlaybackSessionState()
     addBehaviorRestriction(RequireUserGestureToControlControlsManager | RequirePlaybackToControlControlsManager);
 }
 
+void MediaElementSession::suspendBuffering()
+{
+    updateClientDataBuffering();
+}
+
+void MediaElementSession::resumeBuffering()
+{
+    updateClientDataBuffering();
+}
+
+bool MediaElementSession::bufferingSuspended() const
+{
+    if (auto* page = m_element.document().page())
+        return page->mediaBufferingIsSuspended();
+    return true;
+}
+
 bool MediaElementSession::allowsPictureInPicture() const
 {
     return m_element.document().settings().allowsPictureInPictureMediaPlayback();
index 597ba27..ce058c6 100644 (file)
@@ -101,6 +101,10 @@ public:
 
     void resetPlaybackSessionState() override;
 
+    void suspendBuffering() override;
+    void resumeBuffering() override;
+    bool bufferingSuspended() const;
+
     // Restrictions to modify default behaviors.
     enum BehaviorRestrictionFlags : unsigned {
         NoRestrictions = 0,
index 690735d..a40fb87 100644 (file)
@@ -1764,6 +1764,36 @@ void Page::resumeAllMediaPlayback()
 #endif
 }
 
+void Page::suspendAllMediaBuffering()
+{
+#if ENABLE(VIDEO)
+    ASSERT(!m_mediaBufferingIsSuspended);
+    if (m_mediaBufferingIsSuspended)
+        return;
+    m_mediaBufferingIsSuspended = true;
+
+    for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        if (auto* document = frame->document())
+            document->suspendAllMediaBuffering();
+    }
+#endif
+}
+
+void Page::resumeAllMediaBuffering()
+{
+#if ENABLE(VIDEO)
+    ASSERT(m_mediaBufferingIsSuspended);
+    if (!m_mediaBufferingIsSuspended)
+        return;
+    m_mediaBufferingIsSuspended = false;
+
+    for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        if (auto* document = frame->document())
+            document->resumeAllMediaBuffering();
+    }
+#endif
+}
+
 #if ENABLE(MEDIA_SESSION)
 void Page::handleMediaEvent(MediaEventType eventType)
 {
index 9464a8d..ff92753 100644 (file)
@@ -614,7 +614,10 @@ public:
     WEBCORE_EXPORT void stopAllMediaPlayback();
     WEBCORE_EXPORT void suspendAllMediaPlayback();
     WEBCORE_EXPORT void resumeAllMediaPlayback();
-    bool mediaPlaybackIsSuspended() { return m_mediaPlaybackIsSuspended; }
+    bool mediaPlaybackIsSuspended() const { return m_mediaPlaybackIsSuspended; }
+    WEBCORE_EXPORT void suspendAllMediaBuffering();
+    WEBCORE_EXPORT void resumeAllMediaBuffering();
+    bool mediaBufferingIsSuspended() const { return m_mediaBufferingIsSuspended; }
 
 #if ENABLE(MEDIA_SESSION)
     WEBCORE_EXPORT void handleMediaEvent(MediaEventType);
@@ -967,6 +970,7 @@ private:
 
     bool m_shouldEnableICECandidateFilteringByDefault { true };
     bool m_mediaPlaybackIsSuspended { false };
+    bool m_mediaBufferingIsSuspended { false };
 };
 
 inline PageGroup& Page::group()
index 25c1779..87e192f 100644 (file)
@@ -113,6 +113,9 @@ public:
 
     void pauseSession();
     void stopSession();
+
+    virtual void suspendBuffering() { }
+    virtual void resumeBuffering() { }
     
 #if ENABLE(VIDEO)
     uint64_t uniqueIdentifier() const;
index 2050c5e..b9b079d 100644 (file)
@@ -437,6 +437,22 @@ void PlatformMediaSessionManager::resumeAllMediaPlaybackForDocument(const Docume
     });
 }
 
+void PlatformMediaSessionManager::suspendAllMediaBufferingForDocument(const Document& document)
+{
+    forEachSession([&] (PlatformMediaSession& session, size_t) {
+        if (session.client().hostingDocument() == &document)
+            session.suspendBuffering();
+    });
+}
+
+void PlatformMediaSessionManager::resumeAllMediaBufferingForDocument(const Document& document)
+{
+    forEachSession([&] (PlatformMediaSession& session, size_t) {
+        if (session.client().hostingDocument() == &document)
+            session.resumeBuffering();
+    });
+}
+
 void PlatformMediaSessionManager::forEachSession(const Function<void(PlatformMediaSession&, size_t)>& predicate) const
 {
     ++m_iteratingOverSessions;
index 45c7052..b795ff2 100644 (file)
@@ -82,6 +82,8 @@ public:
 
     void suspendAllMediaPlaybackForDocument(const Document&);
     void resumeAllMediaPlaybackForDocument(const Document&);
+    void suspendAllMediaBufferingForDocument(const Document&);
+    void resumeAllMediaBufferingForDocument(const Document&);
 
     enum SessionRestrictionFlags {
         NoRestrictions = 0,
index 159b4d8..eb656a3 100644 (file)
@@ -1,3 +1,35 @@
+2019-02-13  Jer Noble  <jer.noble@apple.com>
+
+        [Cocoa] Media elements will restart network buffering just before suspending
+        https://bugs.webkit.org/show_bug.cgi?id=193691
+
+        Reviewed by Eric Carlson.
+
+        When the WebProcess receives a notification that the process is about to become
+        suspended, it tells the MemoryPressureHandler to release all critical memory. This
+        has the side effect of causing AVFoundation-backed media elements to dump their
+        in-memory caches and start downloading media data again. Instead, media elements
+        should all stop buffering media data during suspension. Add new testing SPI to
+        simulate suspension and resume messages.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _processWillSuspendImminentlyForTesting]):
+        (-[WKWebView _processDidResumeForTesting]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/ios/WKInkPickerView.mm:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::suspendAllMediaBuffering):
+        (WebKit::WebPage::resumeAllMediaBuffering):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::actualPrepareToSuspend):
+        (WebKit::WebProcess::cancelPrepareToSuspend):
+        (WebKit::WebProcess::processDidResume):
+        (WebKit::WebProcess::suspendAllMediaBuffering):
+        (WebKit::WebProcess::resumeAllMediaBuffering):
+        * WebProcess/WebProcess.h:
+
 2019-02-13  Per Arne Vollan  <pvollan@apple.com>
 
         [iOS] Fix sandbox violation during media playback
index 752a3a4..b63efb1 100644 (file)
@@ -7146,6 +7146,18 @@ static WebCore::UserInterfaceLayoutDirection toUserInterfaceLayoutDirection(UISe
     return nil;
 }
 
+- (void)_processWillSuspendImminentlyForTesting
+{
+    if (_page)
+        _page->process().sendProcessWillSuspendImminently();
+}
+
+- (void)_processDidResumeForTesting
+{
+    if (_page)
+        _page->process().sendProcessDidResume();
+}
+
 - (void)_denyNextUserMediaRequest
 {
 #if ENABLE(MEDIA_STREAM)
index 1851099..99fbd94 100644 (file)
@@ -548,6 +548,9 @@ typedef NS_OPTIONS(NSUInteger, _WKRectEdge) {
 @property (nonatomic, readonly) _WKInspector *_inspector WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 @property (nonatomic, readonly) _WKFrameHandle *_mainFrame WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+- (void)_processWillSuspendImminentlyForTesting;
+- (void)_processDidResumeForTesting;
+
 @end
 
 #endif
index ea80979..372e454 100644 (file)
@@ -249,6 +249,13 @@ public:
     void shutDown();
     void maybeShutDown();
 
+    // ProcessThrottlerClient
+    void sendProcessWillSuspendImminently() override;
+    void sendPrepareToSuspend() override;
+    void sendCancelPrepareToSuspend() override;
+    void sendProcessDidResume() override;
+    void didSetAssertionState(AssertionState) override;
+
 protected:
     static uint64_t generatePageID();
     WebProcessProxy(WebProcessPool&, WebsiteDataStore&, IsPrewarmed);
@@ -318,13 +325,6 @@ private:
     void didChangeIsResponsive() override;
     bool mayBecomeUnresponsive() override;
 
-    // ProcessThrottlerClient
-    void sendProcessWillSuspendImminently() override;
-    void sendPrepareToSuspend() override;
-    void sendCancelPrepareToSuspend() override;
-    void sendProcessDidResume() override;
-    void didSetAssertionState(AssertionState) override;
-
     // Implemented in generated WebProcessProxyMessageReceiver.cpp
     void didReceiveWebProcessProxyMessage(IPC::Connection&, IPC::Decoder&);
     void didReceiveSyncWebProcessProxyMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&);
index 331d558..1029edc 100644 (file)
@@ -687,6 +687,17 @@ void WebPage::resumeAllMediaPlayback()
     m_page->resumeAllMediaPlayback();
 }
 
+void WebPage::suspendAllMediaBuffering()
+{
+    m_page->suspendAllMediaBuffering();
+}
+
+void WebPage::resumeAllMediaBuffering()
+{
+    m_page->resumeAllMediaBuffering();
+}
+
+
 void WebPage::reinitializeWebPage(WebPageCreationParameters&& parameters)
 {
     ASSERT(m_drawingArea);
index ba949ba..c80c4b8 100644 (file)
@@ -1148,6 +1148,9 @@ public:
     bool requestDOMPasteAccess();
     WebCore::IntRect rectForElementAtInteractionLocation() const;
 
+    void suspendAllMediaBuffering();
+    void resumeAllMediaBuffering();
+
 private:
     WebPage(uint64_t pageID, WebPageCreationParameters&&);
 
index 2822050..bc13103 100644 (file)
@@ -1379,6 +1379,10 @@ void WebProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shou
 {
     SetForScope<bool> suspensionScope(m_isSuspending, true);
 
+#if ENABLE(VIDEO)
+    suspendAllMediaBuffering();
+#endif
+
     if (!m_suppressMemoryPressureHandler)
         MemoryPressureHandler::singleton().releaseMemory(Critical::Yes, Synchronous::Yes);
 
@@ -1435,7 +1439,11 @@ void WebProcess::cancelPrepareToSuspend()
 #if PLATFORM(IOS_FAMILY)
     accessibilityProcessSuspendedNotification(false);
 #endif
-    
+
+#if ENABLE(VIDEO)
+    resumeAllMediaBuffering();
+#endif
+
     // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
     // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
     if (!m_pageMarkingLayersAsVolatileCounter)
@@ -1500,6 +1508,10 @@ void WebProcess::processDidResume()
 #if PLATFORM(IOS_FAMILY)
     accessibilityProcessSuspendedNotification(false);
 #endif
+
+#if ENABLE(VIDEO)
+    resumeAllMediaBuffering();
+#endif
 }
 
 void WebProcess::sendPrewarmInformation(const URL& url)
@@ -1752,6 +1764,20 @@ void WebProcess::resetMockMediaDevices()
 }
 #endif
 
+#if ENABLE(VIDEO)
+void WebProcess::suspendAllMediaBuffering()
+{
+    for (auto& page : m_pageMap.values())
+        page->suspendAllMediaBuffering();
+}
+
+void WebProcess::resumeAllMediaBuffering()
+{
+    for (auto& page : m_pageMap.values())
+        page->resumeAllMediaBuffering();
+}
+#endif
+
 void WebProcess::clearCurrentModifierStateForTesting()
 {
     PlatformKeyboardEvent::setCurrentModifierState({ });
index b9ca2ee..d98a7a9 100644 (file)
@@ -394,6 +394,11 @@ private:
 #endif
 #endif
 
+#if ENABLE(VIDEO)
+    void suspendAllMediaBuffering();
+    void resumeAllMediaBuffering();
+#endif
+
     void clearCurrentModifierStateForTesting();
 
     RefPtr<WebConnectionToUIProcess> m_webConnection;
index c76865a..4e36cd5 100644 (file)
@@ -1,3 +1,14 @@
+2019-02-13  Jer Noble  <jer.noble@apple.com>
+
+        [Cocoa] Media elements will restart network buffering just before suspending
+        https://bugs.webkit.org/show_bug.cgi?id=193691
+
+        Reviewed by Eric Carlson.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSuspendMediaBuffering.mm: Added.
+        (TEST):
+
 2019-02-13  Aakash Jain  <aakash_jain@apple.com>
 
         [ews-app] Fetch builder id to name mapping
index 7c6e123..e4e2273 100644 (file)
                CDA315981ED53651009F60D3 /* MediaPlaybackSleepAssertion.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDA315961ED53651009F60D3 /* MediaPlaybackSleepAssertion.mm */; };
                CDA3159A1ED548F1009F60D3 /* MediaPlaybackSleepAssertion.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDA315991ED540A5009F60D3 /* MediaPlaybackSleepAssertion.html */; };
                CDA3159D1ED5643F009F60D3 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDA3159C1ED5643F009F60D3 /* IOKit.framework */; };
+               CDA4438E21F7A47700379489 /* ProcessSuspendMediaBuffering.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDA4438D21F7A47700379489 /* ProcessSuspendMediaBuffering.mm */; };
                CDB4115A1E0B00DB00EAD352 /* video-with-muted-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDB411591E09DA8E00EAD352 /* video-with-muted-audio.html */; };
                CDB5DFFF213610FA00D3E189 /* now-playing.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDB5DFFE21360ED800D3E189 /* now-playing.html */; };
                CDBFCC451A9FF45300A7B691 /* FullscreenZoomInitialFrame.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDBFCC431A9FF44800A7B691 /* FullscreenZoomInitialFrame.mm */; };
                CDA315961ED53651009F60D3 /* MediaPlaybackSleepAssertion.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaPlaybackSleepAssertion.mm; sourceTree = "<group>"; };
                CDA315991ED540A5009F60D3 /* MediaPlaybackSleepAssertion.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = MediaPlaybackSleepAssertion.html; sourceTree = "<group>"; };
                CDA3159C1ED5643F009F60D3 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
+               CDA4438D21F7A47700379489 /* ProcessSuspendMediaBuffering.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ProcessSuspendMediaBuffering.mm; sourceTree = "<group>"; };
                CDB411591E09DA8E00EAD352 /* video-with-muted-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "video-with-muted-audio.html"; sourceTree = "<group>"; };
                CDB5DFFE21360ED800D3E189 /* now-playing.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "now-playing.html"; sourceTree = "<group>"; };
                CDBFCC421A9FF44800A7B691 /* FullscreenZoomInitialFrame.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = FullscreenZoomInitialFrame.html; sourceTree = "<group>"; };
                                CD227E43211A4D5D00D285AF /* PreferredAudioBufferSize.mm */,
                                7C1AF7931E8DCBAB002645B9 /* PrepareForMoveToWindow.mm */,
                                41882F0221010A70002FF288 /* ProcessPreWarming.mm */,
+                               CDA4438D21F7A47700379489 /* ProcessSuspendMediaBuffering.mm */,
                                518C1152205B04F9001FF4AE /* ProcessSwapOnNavigation.mm */,
                                5798E2AF1CAF5C2800C5CBA0 /* ProvisionalURLNotChange.mm */,
                                A1C4FB6C1BACCE50003742D0 /* QuickLook.mm */,
                                7CCE7F0C1A411AE600447C4C /* PrivateBrowsingPushStateNoHistoryCallback.cpp in Sources */,
                                4647B1261EBA3B850041D7EF /* ProcessDidTerminate.cpp in Sources */,
                                41882F0321010C0D002FF288 /* ProcessPreWarming.mm in Sources */,
+                               CDA4438E21F7A47700379489 /* ProcessSuspendMediaBuffering.mm in Sources */,
                                518C1153205B0504001FF4AE /* ProcessSwapOnNavigation.mm in Sources */,
                                7C83E0C11D0A652F00FEBCF3 /* ProvisionalURLNotChange.mm in Sources */,
                                041A1E34216FFDBC00789E0A /* PublicSuffix.cpp in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSuspendMediaBuffering.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSuspendMediaBuffering.mm
new file mode 100644 (file)
index 0000000..6dd32de
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_API_ENABLED && WK_HAVE_C_SPI
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+
+#import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+
+TEST(WebKit, ProcessSuspendMediaBuffering)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    WKRetainPtr<WKContextRef> context(AdoptWK, TestWebKitAPI::Util::createContextForInjectedBundleTest("InternalsInjectedBundleTest"));
+    configuration.get().processPool = (WKProcessPool *)context.get();
+    configuration.get()._mediaDataLoadsAutomatically = YES;
+    configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
+
+    __block bool isPlaying = false;
+    [webView performAfterReceivingMessage:@"playing" action:^() { isPlaying = true; }];
+
+    TestWebKitAPI::Util::run(&isPlaying);
+
+    auto isElementAllowedToBuffer = [&] {
+        return [webView stringByEvaluatingJavaScript:@"window.internals.elementShouldBufferData(document.querySelector('video'))"].boolValue;
+    };
+
+    ASSERT_TRUE(isElementAllowedToBuffer());
+
+    [webView _processWillSuspendImminentlyForTesting];
+
+    ASSERT_FALSE(isElementAllowedToBuffer());
+
+    [webView _processDidResumeForTesting];
+
+    ASSERT_TRUE(isElementAllowedToBuffer());
+}
+
+#endif // WK_API_ENABLED && WK_HAVE_C_SPI