Title: [284816] trunk
Revision
284816
Author
[email protected]
Date
2021-10-25 12:25:26 -0700 (Mon, 25 Oct 2021)

Log Message

WebKit ought to be able to play videos without Content-Length HTTP header fields and without range support
https://bugs.webkit.org/show_bug.cgi?id=232174

Patch by Alex Christensen <[email protected]> on 2021-10-25
Reviewed by Geoff Garen.

LayoutTests/imported/w3c:

* web-platform-tests/service-workers/service-worker/fetch-audio-tainting.https-expected.txt:

Source/WebCore:

AVFoundation doesn't like it when you give it a range like 0-1/* because it doesn't know the content length.
To work around this, wait until the entire video is loaded then respond with a known length.
This isn't great, but it's better than not playing the video at all.

In order to fix this, I noticed that the setHTTPHeaderField and setHTTPStatusCode calls were not being reflected in the new NSURLResponse,
so I added a call to initNSURLResponse to update the NSURLResponse.  I'm concerned about what other videos were not having the synthesized
response updated, and I'm surprised non-range-response-supporting videos played without this change.

This makes it so we can play videos like https://trac.webkit.org/export/284633/webkit/trunk/Tools/TestWebKitAPI/Tests/WebKit/test.mp4
which can play in Chrome and Firefox.  Covered by an API test.

* platform/network/cf/ResourceResponse.h:
* platform/network/cocoa/RangeResponseGenerator.mm:
(WebCore::synthesizedResponseForRange):
(WebCore::RangeResponseGenerator::giveResponseToTaskIfBytesInRangeReceived):
* platform/network/cocoa/WebCoreNSURLSession.mm:
(-[WebCoreNSURLSessionDataTask resource:receivedResponse:completionHandler:]):

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (284815 => 284816)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-10-25 19:25:26 UTC (rev 284816)
@@ -1,3 +1,12 @@
+2021-10-25  Alex Christensen  <[email protected]>
+
+        WebKit ought to be able to play videos without Content-Length HTTP header fields and without range support
+        https://bugs.webkit.org/show_bug.cgi?id=232174
+
+        Reviewed by Geoff Garen.
+
+        * web-platform-tests/service-workers/service-worker/fetch-audio-tainting.https-expected.txt:
+
 2021-10-25  Ziran Sun  <[email protected]>
 
         [CSS-grid] Need to set prefer width dirty for the child that has constraints to the grid area

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-audio-tainting.https-expected.txt (284815 => 284816)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-audio-tainting.https-expected.txt	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-audio-tainting.https-expected.txt	2021-10-25 19:25:26 UTC (rev 284816)
@@ -1,6 +1,4 @@
 
 
-Harness Error (TIMEOUT), message = null
+PASS Verify CORS XHR of fetch() in a Service Worker
 
-TIMEOUT Verify CORS XHR of fetch() in a Service Worker Test timed out
-

Modified: trunk/Source/WebCore/ChangeLog (284815 => 284816)


--- trunk/Source/WebCore/ChangeLog	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/Source/WebCore/ChangeLog	2021-10-25 19:25:26 UTC (rev 284816)
@@ -1,3 +1,28 @@
+2021-10-25  Alex Christensen  <[email protected]>
+
+        WebKit ought to be able to play videos without Content-Length HTTP header fields and without range support
+        https://bugs.webkit.org/show_bug.cgi?id=232174
+
+        Reviewed by Geoff Garen.
+
+        AVFoundation doesn't like it when you give it a range like 0-1/* because it doesn't know the content length.
+        To work around this, wait until the entire video is loaded then respond with a known length.
+        This isn't great, but it's better than not playing the video at all.
+
+        In order to fix this, I noticed that the setHTTPHeaderField and setHTTPStatusCode calls were not being reflected in the new NSURLResponse,
+        so I added a call to initNSURLResponse to update the NSURLResponse.  I'm concerned about what other videos were not having the synthesized
+        response updated, and I'm surprised non-range-response-supporting videos played without this change.
+
+        This makes it so we can play videos like https://trac.webkit.org/export/284633/webkit/trunk/Tools/TestWebKitAPI/Tests/WebKit/test.mp4
+        which can play in Chrome and Firefox.  Covered by an API test.
+
+        * platform/network/cf/ResourceResponse.h:
+        * platform/network/cocoa/RangeResponseGenerator.mm:
+        (WebCore::synthesizedResponseForRange):
+        (WebCore::RangeResponseGenerator::giveResponseToTaskIfBytesInRangeReceived):
+        * platform/network/cocoa/WebCoreNSURLSession.mm:
+        (-[WebCoreNSURLSessionDataTask resource:receivedResponse:completionHandler:]):
+
 2021-10-25  Andres Gonzalez  <[email protected]>
 
         Remove childrenInitialized() from the AXCoreObject interface.

Modified: trunk/Source/WebCore/platform/network/cf/ResourceResponse.h (284815 => 284816)


--- trunk/Source/WebCore/platform/network/cf/ResourceResponse.h	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/Source/WebCore/platform/network/cf/ResourceResponse.h	2021-10-25 19:25:26 UTC (rev 284816)
@@ -93,6 +93,10 @@
     void setIsQuickLook(bool isQuickLook) { m_isQuickLook = isQuickLook; }
 #endif
 
+#if PLATFORM(COCOA)
+    void initNSURLResponse() const;
+#endif
+
 private:
     friend class ResourceResponseBase;
 
@@ -100,10 +104,6 @@
     String platformSuggestedFilename() const;
     CertificateInfo platformCertificateInfo() const;
 
-#if PLATFORM(COCOA)
-    void initNSURLResponse() const;
-#endif
-
     static bool platformCompare(const ResourceResponse& a, const ResourceResponse& b);
 
 #if USE(QUICK_LOOK)

Modified: trunk/Source/WebCore/platform/network/cocoa/RangeResponseGenerator.mm (284815 => 284816)


--- trunk/Source/WebCore/platform/network/cocoa/RangeResponseGenerator.mm	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/Source/WebCore/platform/network/cocoa/RangeResponseGenerator.mm	2021-10-25 19:25:26 UTC (rev 284816)
@@ -73,13 +73,13 @@
     ASSERT(isMainThread());
 }
 
-static ResourceResponse synthesizedResponseForRange(const ResourceResponse& originalResponse, const ParsedRequestRange& parsedRequestRange, std::optional<size_t> totalContentLength)
+static ResourceResponse synthesizedResponseForRange(const ResourceResponse& originalResponse, const ParsedRequestRange& parsedRequestRange, size_t totalContentLength)
 {
     ASSERT(isMainThread());
     auto begin = parsedRequestRange.begin;
     auto end = parsedRequestRange.end;
 
-    auto newContentRange = makeString("bytes ", begin, "-", end, "/", (totalContentLength ? makeString(*totalContentLength) : "*"));
+    auto newContentRange = makeString("bytes ", begin, "-", end, "/", totalContentLength);
     auto newContentLength = makeString(end - begin + 1);
 
     ResourceResponse newResponse = originalResponse;
@@ -87,6 +87,9 @@
     newResponse.setHTTPHeaderField(HTTPHeaderName::ContentLength, newContentLength);
     constexpr auto partialContent = 206;
     newResponse.setHTTPStatusCode(partialContent);
+    
+    // Values from setHTTPStatusCode and setHTTPHeaderField are not reflected in the newly generated response without this.
+    newResponse.initNSURLResponse();
 
     return newResponse;
 }
@@ -106,6 +109,11 @@
     auto buffer = data.buffer;
     auto bufferSize = buffer->size();
 
+    // FIXME: We ought to be able to just make a range with a * after the / but AVFoundation doesn't accept such ranges.
+    // Instead, we just wait until the load has completed, at which time we will know the content length from the buffer length.
+    if (!expectedContentLength)
+        return;
+
     if (bufferSize < range.begin)
         return;
     
@@ -143,7 +151,7 @@
 
     switch (taskData->responseState) {
     case Data::TaskData::ResponseState::NotSynthesizedYet: {
-        auto response = synthesizedResponseForRange(data.originalResponse, range, expectedContentLength);
+        auto response = synthesizedResponseForRange(data.originalResponse, range, *expectedContentLength);
         [task resource:nullptr receivedResponse:response completionHandler:[giveBytesToTask = WTFMove(giveBytesToTask), taskData = WeakPtr { taskData }, task = retainPtr(task)] (WebCore::ShouldContinuePolicyCheck shouldContinue) {
             if (taskData)
                 taskData->responseState = Data::TaskData::ResponseState::SessionCalledCompletionHandler;

Modified: trunk/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm (284815 => 284816)


--- trunk/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm	2021-10-25 19:25:26 UTC (rev 284816)
@@ -863,7 +863,6 @@
     ASSERT_UNUSED(resource, !resource || resource == _resource);
     ASSERT(isMainThread());
     [self.session task:self didReceiveResponseFromOrigin:SecurityOrigin::create(response.url())];
-    // FIXME: Think about this and make sure it's safe.
     [self.session task:self didReceiveCORSAccessCheckResult:resource ? resource->didPassAccessControlCheck() : YES];
     self.countOfBytesExpectedToReceive = response.expectedContentLength();
     RetainPtr<NSURLResponse> strongResponse = response.nsURLResponse();

Modified: trunk/Tools/ChangeLog (284815 => 284816)


--- trunk/Tools/ChangeLog	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/Tools/ChangeLog	2021-10-25 19:25:26 UTC (rev 284816)
@@ -1,3 +1,13 @@
+2021-10-25  Alex Christensen  <[email protected]>
+
+        WebKit ought to be able to play videos without Content-Length HTTP header fields and without range support
+        https://bugs.webkit.org/show_bug.cgi?id=232174
+
+        Reviewed by Geoff Garen.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm:
+        (TestWebKitAPI::TEST):
+
 2021-10-25  Ryan Haddad  <[email protected]>
 
         Bring up queues for Monterey

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm (284815 => 284816)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm	2021-10-25 19:10:30 UTC (rev 284815)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm	2021-10-25 19:25:26 UTC (rev 284816)
@@ -163,8 +163,8 @@
     respondToRequests = [&] (Connection connection) {
         connection.receiveHTTPRequest([&, connection] (Vector<char>&& request) {
             auto sendResponse = [&, connection] (HTTPResponse response, HTTPResponse::IncludeContentLength includeContentLength) {
-                connection.send(response.serialize(includeContentLength), [&, connection] {
-                    respondToRequests(connection);
+                connection.send(response.serialize(includeContentLength), [connection] () mutable {
+                    connection.terminate();
                 });
             };
             totalRequests++;
@@ -181,7 +181,7 @@
     HTTPServer server([&](Connection connection) {
         respondToRequests(connection);
     });
-    runVideoTest(server.request(), "error");
+    runVideoTest(server.request(), "playing");
     EXPECT_EQ(totalRequests, 2u);
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to