Changeset 272908 in webkit
- Timestamp:
- Feb 16, 2021 8:59:26 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r272906 r272908 1 2021-02-16 Alex Christensen <achristensen@webkit.org> 2 3 Synthesize range responses if needed in WebCoreNSURLSession 4 https://bugs.webkit.org/show_bug.cgi?id=221072 5 6 Reviewed by Geoff Garen. 7 8 When we make a media request with a Range HTTP header field and the server doesn't respond with a 206 with Content-Range header field, 9 until now we would just fail to play the video. In order to successfully play these videos, I introduce the RangeResponseGenerator class, 10 which will receive the data for a request for such a video and feed the data into WebCoreNSURLSession as the requested ranges are received. 11 Seeking is problematic, but at least we will try our best to play the video. 12 13 I added API tests that try to play a video that didn't play before using a server that doesn't support range requests. Manual verification is also necessary. 14 15 * Sources.txt: 16 * SourcesCocoa.txt: 17 * WebCore.xcodeproj/project.pbxproj: 18 * platform/graphics/PlatformMediaResourceLoader.h: 19 (WebCore::PlatformMediaResource::setClient): 20 * platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm: 21 (WebCore::PlatformResourceMediaLoader::create): 22 * platform/network/ParsedRequestRange.cpp: Added. 23 (WebCore::ParsedRequestRange::parse): 24 * platform/network/ParsedRequestRange.h: Added. 25 (WebCore::ParsedRequestRange::begin const): 26 (WebCore::ParsedRequestRange::end const): 27 (WebCore::ParsedRequestRange::ParsedRequestRange): 28 * platform/network/cocoa/RangeResponseGenerator.h: Added. 29 * platform/network/cocoa/RangeResponseGenerator.mm: Added. 30 (WebCore::RangeResponseGenerator::Data::Data): 31 (WebCore::RangeResponseGenerator::Data::TaskData::TaskData): 32 (WebCore::synthesizedResponseForRange): 33 (WebCore::RangeResponseGenerator::removeTask): 34 (WebCore::RangeResponseGenerator::giveResponseToTaskIfBytesInRangeReceived): 35 (WebCore::RangeResponseGenerator::expectedContentLengthFromData): 36 (WebCore::RangeResponseGenerator::giveResponseToTasksWithFinishedRanges): 37 (WebCore::RangeResponseGenerator::willHandleRequest): 38 (WebCore::RangeResponseGenerator::willSynthesizeRangeResponses): 39 * platform/network/cocoa/WebCoreNSURLSession.h: 40 * platform/network/cocoa/WebCoreNSURLSession.mm: 41 (-[WebCoreNSURLSession rangeResponseGenerator]): 42 (-[WebCoreNSURLSession dataTaskWithURL:]): 43 (WebCore::WebCoreNSURLSessionDataTaskClient::dataSent): 44 (WebCore::WebCoreNSURLSessionDataTaskClient::responseReceived): 45 (WebCore::WebCoreNSURLSessionDataTaskClient::shouldCacheResponse): 46 (WebCore::WebCoreNSURLSessionDataTaskClient::dataReceived): 47 (WebCore::WebCoreNSURLSessionDataTaskClient::redirectReceived): 48 (WebCore::WebCoreNSURLSessionDataTaskClient::accessControlCheckFailed): 49 (WebCore::WebCoreNSURLSessionDataTaskClient::loadFailed): 50 (WebCore::WebCoreNSURLSessionDataTaskClient::loadFinished): 51 (-[WebCoreNSURLSessionDataTask _restart]): 52 (-[WebCoreNSURLSessionDataTask _finish]): 53 (-[WebCoreNSURLSessionDataTask resource:sentBytes:totalBytesToBeSent:]): 54 (-[WebCoreNSURLSessionDataTask resource:receivedResponse:completionHandler:]): 55 (-[WebCoreNSURLSessionDataTask resource:shouldCacheResponse:]): 56 (-[WebCoreNSURLSessionDataTask resource:receivedData:length:]): 57 (-[WebCoreNSURLSessionDataTask resource:receivedRedirect:request:completionHandler:]): 58 (-[WebCoreNSURLSessionDataTask _resource:loadFinishedWithError:metrics:]): 59 (-[WebCoreNSURLSessionDataTask resource:accessControlCheckFailedWithError:]): 60 (-[WebCoreNSURLSessionDataTask resource:loadFailedWithError:]): 61 (-[WebCoreNSURLSessionDataTask resourceFinished:metrics:]): 62 (-[WebCoreNSURLSessionDataTask initWithSession:identifier:URL:]): Deleted. 63 1 64 2021-02-16 Antti Koivisto <antti@apple.com> 2 65 -
trunk/Source/WebCore/Headers.cmake
r272764 r272908 1413 1413 platform/network/ParsedContentRange.h 1414 1414 platform/network/ParsedContentType.h 1415 platform/network/ParsedRequestRange.h 1415 1416 platform/network/ProtectionSpace.h 1416 1417 platform/network/ProtectionSpaceBase.h -
trunk/Source/WebCore/Sources.txt
r272878 r272908 2126 2126 platform/network/ParsedContentRange.cpp 2127 2127 platform/network/ParsedContentType.cpp 2128 platform/network/ParsedRequestRange.cpp 2128 2129 platform/network/ProtectionSpaceBase.cpp 2129 2130 platform/network/ProxyServer.cpp -
trunk/Source/WebCore/SourcesCocoa.txt
r272878 r272908 570 570 platform/network/cocoa/NetworkStorageSessionCocoa.mm 571 571 platform/network/cocoa/ProtectionSpaceCocoa.mm 572 platform/network/cocoa/RangeResponseGenerator.mm 572 573 platform/network/cocoa/ResourceRequestCocoa.mm 573 574 platform/network/cocoa/ResourceResponseCocoa.mm @no-unify // Unsafe to unify until rdar://problem/48853137 is resolved -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r272878 r272908 1946 1946 5C4304B1191AC908000E2BC0 /* EXTShaderTextureLOD.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4304AE191AC908000E2BC0 /* EXTShaderTextureLOD.h */; }; 1947 1947 5C4304B6191AEF46000E2BC0 /* JSEXTShaderTextureLOD.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4304B4191AEF46000E2BC0 /* JSEXTShaderTextureLOD.h */; }; 1948 5C4A0FD725C3435000D9EE97 /* RangeResponseGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4A0FD525C342C800D9EE97 /* RangeResponseGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1949 5C4A0FDA25C3449A00D9EE97 /* ParsedRequestRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4A0FD825C3446C00D9EE97 /* ParsedRequestRange.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1948 1950 5C53DCE124465DFC00A93124 /* ApplePaySetupFeatureWebCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C53DCCF2446449900A93124 /* ApplePaySetupFeatureWebCore.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1949 1951 5C53DCE724468AD200A93124 /* PaymentInstallmentConfigurationWebCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C53DCCE2446449900A93124 /* PaymentInstallmentConfigurationWebCore.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 9502 9504 5C4304B3191AEF46000E2BC0 /* JSEXTShaderTextureLOD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEXTShaderTextureLOD.cpp; sourceTree = "<group>"; }; 9503 9505 5C4304B4191AEF46000E2BC0 /* JSEXTShaderTextureLOD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEXTShaderTextureLOD.h; sourceTree = "<group>"; }; 9506 5C4A0FD325C342C700D9EE97 /* RangeResponseGenerator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RangeResponseGenerator.mm; sourceTree = "<group>"; }; 9507 5C4A0FD525C342C800D9EE97 /* RangeResponseGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RangeResponseGenerator.h; sourceTree = "<group>"; }; 9508 5C4A0FD625C342DB00D9EE97 /* CertificateInfoCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CertificateInfoCocoa.mm; sourceTree = "<group>"; }; 9509 5C4A0FD825C3446C00D9EE97 /* ParsedRequestRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParsedRequestRange.h; sourceTree = "<group>"; }; 9510 5C4A0FD925C3446D00D9EE97 /* ParsedRequestRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParsedRequestRange.cpp; sourceTree = "<group>"; }; 9504 9511 5C5381AF1D8793E000E2EBE6 /* URLSearchParams.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = URLSearchParams.idl; sourceTree = "<group>"; }; 9505 9512 5C5381B01D87D45700E2EBE6 /* URLSearchParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLSearchParams.cpp; sourceTree = "<group>"; }; … … 21849 21856 447958021643B47B001E0A7F /* ParsedContentType.cpp */, 21850 21857 447958031643B47B001E0A7F /* ParsedContentType.h */, 21858 5C4A0FD925C3446D00D9EE97 /* ParsedRequestRange.cpp */, 21859 5C4A0FD825C3446C00D9EE97 /* ParsedRequestRange.h */, 21851 21860 37BAAE571980D1DD005DFE71 /* ProtectionSpace.h */, 21852 21861 514C765F0CE923A1007EF3CD /* ProtectionSpaceBase.cpp */, … … 22933 22942 isa = PBXGroup; 22934 22943 children = ( 22944 5C4A0FD625C342DB00D9EE97 /* CertificateInfoCocoa.mm */, 22935 22945 51D1248C1E736456002B2820 /* CookieCocoa.mm */, 22936 22946 5120BBAD1F1CE77000EFEBF1 /* CookieStorageObserver.h */, … … 22943 22953 372ADA37197F47B900FC501E /* ProtectionSpaceCocoa.h */, 22944 22954 372ADA39197F687600FC501E /* ProtectionSpaceCocoa.mm */, 22955 5C4A0FD525C342C800D9EE97 /* RangeResponseGenerator.h */, 22956 5C4A0FD325C342C700D9EE97 /* RangeResponseGenerator.mm */, 22945 22957 7E7DE1FC195CEF260035363B /* ResourceRequestCocoa.mm */, 22946 22958 A1F78D0B1C25422C00245446 /* ResourceResponseCocoa.mm */, … … 34016 34028 CDCD41E81C3DDB0A00965D99 /* ParsedContentRange.h in Headers */, 34017 34029 447958041643B49A001E0A7F /* ParsedContentType.h in Headers */, 34030 5C4A0FDA25C3449A00D9EE97 /* ParsedRequestRange.h in Headers */, 34018 34031 536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */, 34019 34032 F55B3DCA1251F12D003EF269 /* PasswordInputType.h in Headers */, … … 34219 34232 93D9D53C0DA27E180077216C /* RangeBoundaryPoint.h in Headers */, 34220 34233 F55B3DCE1251F12D003EF269 /* RangeInputType.h in Headers */, 34234 5C4A0FD725C3435000D9EE97 /* RangeResponseGenerator.h in Headers */, 34221 34235 6E84E9E117668BF100815B68 /* RasterShape.h in Headers */, 34222 34236 A84D827C11D333ED00972990 /* RawDataDocumentParser.h in Headers */, -
trunk/Source/WebCore/platform/graphics/PlatformMediaResourceLoader.h
r272764 r272908 42 42 class ResourceResponse; 43 43 44 class PlatformMediaResourceClient {44 class PlatformMediaResourceClient : public RefCounted<PlatformMediaResourceClient> { 45 45 public: 46 46 virtual ~PlatformMediaResourceClient() = default; … … 82 82 virtual bool didPassAccessControlCheck() const { return false; } 83 83 84 void setClient( std::unique_ptr<PlatformMediaResourceClient>&& client) { m_client = WTFMove(client); }84 void setClient(RefPtr<PlatformMediaResourceClient>&& client) { m_client = WTFMove(client); } 85 85 PlatformMediaResourceClient* client() { return m_client.get(); } 86 86 87 87 protected: 88 std::unique_ptr<PlatformMediaResourceClient> m_client;88 RefPtr<PlatformMediaResourceClient> m_client; 89 89 }; 90 90 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm
r272764 r272908 171 171 return nullptr; 172 172 auto* resourcePointer = resource.get(); 173 auto client = std::unique_ptr<PlatformResourceMediaLoader>(new PlatformResourceMediaLoader { parent, resource.releaseNonNull() });173 auto client = adoptRef(*new PlatformResourceMediaLoader { parent, resource.releaseNonNull() }); 174 174 auto result = makeWeakPtr(client.get()); 175 175 -
trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
r272764 r272908 700 700 members->resource = members->loader->requestResource(ResourceRequest(request), loadOptions); 701 701 if (members->resource) { 702 members->resource->setClient( makeUnique<CachedResourceStreamingClient>(protector.get(), ResourceRequest(request), requestNumber));702 members->resource->setClient(adoptRef(*new CachedResourceStreamingClient(protector.get(), ResourceRequest(request), requestNumber))); 703 703 GST_DEBUG_OBJECT(protector.get(), "Started request R%u", requestNumber); 704 704 } else { -
trunk/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.h
r272764 r272908 24 24 */ 25 25 26 #import "RangeResponseGenerator.h" 26 27 #import "SecurityOrigin.h" 27 28 #import <Foundation/NSURLSession.h> 29 #import <wtf/CompletionHandler.h> 28 30 #import <wtf/HashSet.h> 29 31 #import <wtf/Lock.h> … … 42 44 namespace WebCore { 43 45 class CachedResourceRequest; 46 class NetworkLoadMetrics; 44 47 class PlatformMediaResource; 45 48 class PlatformMediaResourceLoader; 49 class ResourceError; 50 class ResourceRequest; 51 class ResourceResponse; 46 52 class WebCoreNSURLSessionDataTaskClient; 53 enum class ShouldContinuePolicyCheck : bool; 47 54 } 48 55 49 enum class WebCoreNSURLSessionCORSAccessCheckResults {56 enum class WebCoreNSURLSessionCORSAccessCheckResults : uint8_t { 50 57 Unknown, 51 58 Pass, … … 68 75 OSObjectPtr<dispatch_queue_t> _internalQueue; 69 76 WebCoreNSURLSessionCORSAccessCheckResults _corsResults; 77 WebCore::RangeResponseGenerator _rangeResponseGenerator; 70 78 } 71 79 - (id)initWithResourceLoader:(WebCore::PlatformMediaResourceLoader&)loader delegate:(id<NSURLSessionTaskDelegate>)delegate delegateQueue:(NSOperationQueue*)queue; … … 111 119 112 120 @interface WebCoreNSURLSessionDataTask : NSObject { 113 __unsafe_unretained WebCoreNSURLSession *_session;121 WeakObjCPtr<WebCoreNSURLSession> _session; 114 122 RefPtr<WebCore::PlatformMediaResource> _resource; 115 123 RetainPtr<NSURLResponse> _response; … … 144 152 @end 145 153 154 @interface WebCoreNSURLSessionDataTask (WebKitInternal) 155 - (void)resource:(nullable WebCore::PlatformMediaResource*)resource sentBytes:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent; 156 - (void)resource:(nullable WebCore::PlatformMediaResource*)resource receivedResponse:(const WebCore::ResourceResponse&)response completionHandler:(CompletionHandler<void(WebCore::ShouldContinuePolicyCheck)>&&)completionHandler; 157 - (BOOL)resource:(nullable WebCore::PlatformMediaResource*)resource shouldCacheResponse:(const WebCore::ResourceResponse&)response; 158 - (void)resource:(nullable WebCore::PlatformMediaResource*)resource receivedData:(const char*)data length:(int)length; 159 - (void)resource:(nullable WebCore::PlatformMediaResource*)resource receivedRedirect:(const WebCore::ResourceResponse&)response request:(WebCore::ResourceRequest&&)request completionHandler:(CompletionHandler<void(WebCore::ResourceRequest&&)>&&)completionHandler; 160 - (void)resource:(nullable WebCore::PlatformMediaResource*)resource accessControlCheckFailedWithError:(const WebCore::ResourceError&)error; 161 - (void)resource:(nullable WebCore::PlatformMediaResource*)resource loadFailedWithError:(const WebCore::ResourceError&)error; 162 - (void)resourceFinished:(nullable WebCore::PlatformMediaResource*)resource metrics:(const WebCore::NetworkLoadMetrics&)metrics; 163 @end 164 146 165 NS_ASSUME_NONNULL_END -
trunk/Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm
r272764 r272908 28 28 29 29 #import "CachedResourceRequest.h" 30 #import "ParsedRequestRange.h" 30 31 #import "PlatformMediaResourceLoader.h" 31 32 #import "SubresourceLoader.h" 32 33 #import <wtf/BlockPtr.h> 33 34 #import <wtf/CompletionHandler.h> 35 #import <wtf/WeakObjCPtr.h> 34 36 #import <wtf/cocoa/VectorCocoa.h> 35 37 … … 204 206 - (void)task:(WebCoreNSURLSessionDataTask *)task didReceiveCORSAccessCheckResult:(BOOL)result; 205 207 - (void)task:(WebCoreNSURLSessionDataTask *)task didReceiveResponseFromOrigin:(Ref<WebCore::SecurityOrigin>&&)origin; 208 - (WebCore::RangeResponseGenerator&)rangeResponseGenerator; 206 209 @end 207 210 208 211 @interface WebCoreNSURLSessionDataTask () 209 212 - (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier request:(NSURLRequest *)request; 210 - (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier URL:(NSURL *)url;211 213 - (void)_restart; 212 214 - (void)_cancel; 213 - (void)_finish;214 215 @property (assign) WebCoreNSURLSession * _Nullable session; 215 216 216 - (void)resource:(PlatformMediaResource&)resource sentBytes:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent;217 - (void)resource:(PlatformMediaResource&)resource receivedResponse:(const ResourceResponse&)response completionHandler:(CompletionHandler<void(ShouldContinuePolicyCheck)>&&)completionHandler;218 - (BOOL)resource:(PlatformMediaResource&)resource shouldCacheResponse:(const ResourceResponse&)response;219 - (void)resource:(PlatformMediaResource&)resource receivedData:(const char*)data length:(int)length;220 - (void)resource:(PlatformMediaResource&)resource receivedRedirect:(const ResourceResponse&)response request:(ResourceRequest&&)request completionHandler:(CompletionHandler<void(ResourceRequest&&)>&&)completionHandler;221 - (void)resource:(PlatformMediaResource&)resource accessControlCheckFailedWithError:(const ResourceError&)error;222 - (void)resource:(PlatformMediaResource&)resource loadFailedWithError:(const ResourceError&)error;223 - (void)resourceFinished:(PlatformMediaResource&)resource metrics:(const NetworkLoadMetrics&)metrics;224 217 @end 225 218 … … 312 305 } 313 306 307 - (WebCore::RangeResponseGenerator&)rangeResponseGenerator 308 { 309 return _rangeResponseGenerator; 310 } 311 314 312 #pragma mark - NSURLSession API 315 313 @dynamic delegate; … … 456 454 - (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url 457 455 { 458 if (_invalidated) 459 return nil; 460 461 WebCoreNSURLSessionDataTask *task = [[WebCoreNSURLSessionDataTask alloc] initWithSession:self identifier:_nextTaskIdentifier++ URL:url]; 462 { 463 Locker<Lock> locker(_dataTasksLock); 464 _dataTasks.add(task); 465 } 466 return (NSURLSessionDataTask *)[task autorelease]; 456 return [self dataTaskWithRequest:[NSURLRequest requestWithURL:url]]; 467 457 } 468 458 … … 572 562 private: 573 563 Lock m_taskLock; 574 We bCoreNSURLSessionDataTask *m_task;564 WeakObjCPtr<WebCoreNSURLSessionDataTask> m_task; 575 565 }; 576 566 … … 587 577 return; 588 578 589 [m_task resource: resource sentBytes:bytesSent totalBytesToBeSent:totalBytesToBeSent];579 [m_task resource:&resource sentBytes:bytesSent totalBytesToBeSent:totalBytesToBeSent]; 590 580 } 591 581 592 582 void WebCoreNSURLSessionDataTaskClient::responseReceived(PlatformMediaResource& resource, const ResourceResponse& response, CompletionHandler<void(ShouldContinuePolicyCheck)>&& completionHandler) 593 583 { 584 auto protectedThis = makeRef(*this); 594 585 LockHolder locker(m_taskLock); 595 586 if (!m_task) 596 587 return completionHandler(ShouldContinuePolicyCheck::No); 597 588 598 [m_task resource: resource receivedResponse:response completionHandler:WTFMove(completionHandler)];589 [m_task resource:&resource receivedResponse:response completionHandler:WTFMove(completionHandler)]; 599 590 } 600 591 … … 605 596 return false; 606 597 607 return [m_task resource: resource shouldCacheResponse:response];598 return [m_task resource:&resource shouldCacheResponse:response]; 608 599 } 609 600 … … 614 605 return; 615 606 616 [m_task resource: resource receivedData:data length:length];607 [m_task resource:&resource receivedData:data length:length]; 617 608 } 618 609 … … 623 614 return; 624 615 625 [m_task resource: resource receivedRedirect:response request:WTFMove(request) completionHandler: [completionHandler = WTFMove(completionHandler)] (auto&& request) mutable {616 [m_task resource:&resource receivedRedirect:response request:WTFMove(request) completionHandler: [completionHandler = WTFMove(completionHandler)] (auto&& request) mutable { 626 617 callOnMainThread([request = request.isolatedCopy(), completionHandler = WTFMove(completionHandler)] () mutable { 627 618 completionHandler(WTFMove(request)); … … 636 627 return; 637 628 638 [m_task resource: resource accessControlCheckFailedWithError:error];629 [m_task resource:&resource accessControlCheckFailedWithError:error]; 639 630 } 640 631 … … 645 636 return; 646 637 647 [m_task resource: resource loadFailedWithError:error];638 [m_task resource:&resource loadFailedWithError:error]; 648 639 } 649 640 … … 654 645 return; 655 646 656 [m_task resourceFinished: resource metrics:metrics];647 [m_task resourceFinished:&resource metrics:metrics]; 657 648 } 658 649 … … 662 653 663 654 @implementation WebCoreNSURLSessionDataTask 664 - (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier URL:(NSURL *)url665 {666 self.taskIdentifier = identifier;667 self.session = session;668 self.state = NSURLSessionTaskStateSuspended;669 self.priority = NSURLSessionTaskPriorityDefault;670 self.originalRequest = self.currentRequest = [NSURLRequest requestWithURL:url];671 672 return self;673 }674 675 655 - (id)initWithSession:(WebCoreNSURLSession *)session identifier:(NSUInteger)identifier request:(NSURLRequest *)request 676 656 { … … 709 689 [self _cancel]; 710 690 691 if ([self.session rangeResponseGenerator].willHandleRequest(self, self.originalRequest)) 692 return; 693 711 694 _resource = self.session.loader.requestResource(self.originalRequest, PlatformMediaResourceLoader::LoadOption::DisallowCaching); 712 695 if (_resource) 713 _resource->setClient( makeUnique<WebCoreNSURLSessionDataTaskClient>(self));696 _resource->setClient(adoptRef(*new WebCoreNSURLSessionDataTaskClient(self))); 714 697 } 715 698 … … 724 707 } 725 708 726 - (void)_finish727 {728 ASSERT(isMainThread());729 if (_resource)730 [self resourceFinished:*_resource metrics:NetworkLoadMetrics { }];731 }732 733 709 #pragma mark - NSURLSession API 734 @synthesize session = _session;735 710 @synthesize taskIdentifier = _taskIdentifier; 736 711 @synthesize originalRequest = _originalRequest; … … 745 720 @synthesize priority = _priority; 746 721 722 - (WebCoreNSURLSession *)session 723 { 724 return _session.get().get(); 725 } 726 727 - (void)setSession:(WebCoreNSURLSession *)session 728 { 729 _session = session; 730 } 731 747 732 - (NSURLResponse *)response 748 733 { … … 752 737 - (void)cancel 753 738 { 739 if (self.state == NSURLSessionTaskStateCompleted) 740 return; 754 741 self.state = NSURLSessionTaskStateCanceling; 755 callOnMainThread([protectedSelf = RetainPtr<WebCoreNSURLSessionDataTask>(self)] {742 callOnMainThread([protectedSelf = retainPtr(self)] { 756 743 [protectedSelf _cancel]; 757 [protectedSelf _ finish];744 [protectedSelf _resource:nullptr loadFinishedWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil] metrics:NetworkLoadMetrics { }]; 758 745 }); 759 746 } … … 807 794 #pragma mark - PlatformMediaResourceClient callbacks 808 795 809 - (void)resource:(PlatformMediaResource &)resource sentBytes:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent810 { 811 ASSERT_UNUSED(resource, &resource == _resource);796 - (void)resource:(PlatformMediaResource*)resource sentBytes:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent 797 { 798 ASSERT_UNUSED(resource, !resource || resource == _resource); 812 799 UNUSED_PARAM(bytesSent); 813 800 UNUSED_PARAM(totalBytesToBeSent); … … 815 802 } 816 803 817 - (void)resource:(PlatformMediaResource &)resource receivedResponse:(const ResourceResponse&)response completionHandler:(CompletionHandler<void(ShouldContinuePolicyCheck)>&&)completionHandler804 - (void)resource:(PlatformMediaResource*)resource receivedResponse:(const ResourceResponse&)response completionHandler:(CompletionHandler<void(ShouldContinuePolicyCheck)>&&)completionHandler 818 805 { 819 806 ASSERT(response.source() == ResourceResponse::Source::Network || response.source() == ResourceResponse::Source::DiskCache || response.source() == ResourceResponse::Source::DiskCacheAfterValidation || response.source() == ResourceResponse::Source::ServiceWorker); 820 ASSERT_UNUSED(resource, &resource == _resource);807 ASSERT_UNUSED(resource, !resource || resource == _resource); 821 808 ASSERT(isMainThread()); 822 809 [self.session task:self didReceiveResponseFromOrigin:SecurityOrigin::create(response.url())]; 823 [self.session task:self didReceiveCORSAccessCheckResult:resource.didPassAccessControlCheck()]; 810 // FIXME: Think about this and make sure it's safe. 811 [self.session task:self didReceiveCORSAccessCheckResult:resource ? resource->didPassAccessControlCheck() : YES]; 824 812 self.countOfBytesExpectedToReceive = response.expectedContentLength(); 825 RetainPtr<NSURLResponse> strongResponse { response.nsURLResponse() }; 813 RetainPtr<NSURLResponse> strongResponse = response.nsURLResponse(); 814 815 if (resource && self.session && [self.session rangeResponseGenerator].willSynthesizeRangeResponses(self, *resource, response)) 816 return completionHandler(ShouldContinuePolicyCheck::Yes); 817 826 818 RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self }; 827 819 if (!self.session) … … 851 843 } 852 844 853 - (BOOL)resource:(PlatformMediaResource &)resource shouldCacheResponse:(const ResourceResponse&)response854 { 855 ASSERT_UNUSED(resource, &resource == _resource);845 - (BOOL)resource:(PlatformMediaResource*)resource shouldCacheResponse:(const ResourceResponse&)response 846 { 847 ASSERT_UNUSED(resource, !resource || resource == _resource); 856 848 857 849 ASSERT(isMainThread()); … … 861 853 } 862 854 863 - (void)resource:(PlatformMediaResource &)resource receivedData:(const char*)data length:(int)length864 { 865 ASSERT_UNUSED(resource, &resource == _resource);855 - (void)resource:(PlatformMediaResource*)resource receivedData:(const char*)data length:(int)length 856 { 857 ASSERT_UNUSED(resource, !resource || resource == _resource); 866 858 RetainPtr<NSData> nsData = adoptNS([[NSData alloc] initWithBytes:data length:length]); 867 859 RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self }; … … 874 866 } 875 867 876 - (void)resource:(PlatformMediaResource &)resource receivedRedirect:(const ResourceResponse&)response request:(ResourceRequest&&)request completionHandler:(CompletionHandler<void(ResourceRequest&&)>&&)completionHandler877 { 878 ASSERT_UNUSED(resource, &resource == _resource);868 - (void)resource:(PlatformMediaResource*)resource receivedRedirect:(const ResourceResponse&)response request:(ResourceRequest&&)request completionHandler:(CompletionHandler<void(ResourceRequest&&)>&&)completionHandler 869 { 870 ASSERT_UNUSED(resource, !resource || resource == _resource); 879 871 [self.session addDelegateOperation:[strongSelf = retainPtr(self), response = retainPtr(response.nsURLResponse()), request = request.isolatedCopy(), completionHandler = WTFMove(completionHandler)] () mutable { 880 872 if (![response isKindOfClass:[NSHTTPURLResponse class]]) { … … 906 898 } 907 899 908 - (void)_resource:(PlatformMediaResource &)resource loadFinishedWithError:(NSError *)error metrics:(const NetworkLoadMetrics&)metrics909 { 910 ASSERT_UNUSED(resource, &resource == _resource);900 - (void)_resource:(PlatformMediaResource*)resource loadFinishedWithError:(NSError *)error metrics:(const NetworkLoadMetrics&)metrics 901 { 902 ASSERT_UNUSED(resource, !resource || resource == _resource); 911 903 if (self.state == NSURLSessionTaskStateCompleted) 912 904 return; … … 931 923 } 932 924 933 - (void)resource:(PlatformMediaResource &)resource accessControlCheckFailedWithError:(const ResourceError&)error925 - (void)resource:(PlatformMediaResource*)resource accessControlCheckFailedWithError:(const ResourceError&)error 934 926 { 935 927 [self _resource:resource loadFinishedWithError:error.nsError() metrics:NetworkLoadMetrics { }]; 936 928 } 937 929 938 - (void)resource:(PlatformMediaResource &)resource loadFailedWithError:(const ResourceError&)error930 - (void)resource:(PlatformMediaResource*)resource loadFailedWithError:(const ResourceError&)error 939 931 { 940 932 [self _resource:resource loadFinishedWithError:error.nsError() metrics:NetworkLoadMetrics { }]; 941 933 } 942 934 943 - (void)resourceFinished:(PlatformMediaResource &)resource metrics:(const NetworkLoadMetrics&)metrics935 - (void)resourceFinished:(PlatformMediaResource*)resource metrics:(const NetworkLoadMetrics&)metrics 944 936 { 945 937 [self _resource:resource loadFinishedWithError:nil metrics:metrics]; -
trunk/Source/WebKit/ChangeLog
r272905 r272908 1 2021-02-16 Alex Christensen <achristensen@webkit.org> 2 3 Synthesize range responses if needed in WebCoreNSURLSession 4 https://bugs.webkit.org/show_bug.cgi?id=221072 5 6 Reviewed by Geoff Garen. 7 8 * WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp: 9 (WebKit::MediaPlayerPrivateRemote::requestResource): 10 1 11 2021-02-16 Kimmo Kinnunen <kkinnunen@apple.com> 2 12 -
trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp
r272764 r272908 1181 1181 } 1182 1182 // PlatformMediaResource owns the PlatformMediaResourceClient 1183 resource->setClient( makeUnique<RemoteMediaResourceProxy>(connection(), *resource, remoteMediaResourceIdentifier));1183 resource->setClient(adoptRef(*new RemoteMediaResourceProxy(connection(), *resource, remoteMediaResourceIdentifier))); 1184 1184 m_mediaResources.add(remoteMediaResourceIdentifier, WTFMove(resource)); 1185 1185 -
trunk/Tools/ChangeLog
r272894 r272908 1 2021-02-16 Alex Christensen <achristensen@webkit.org> 2 3 Synthesize range responses if needed in WebCoreNSURLSession 4 https://bugs.webkit.org/show_bug.cgi?id=221072 5 6 Reviewed by Geoff Garen. 7 8 * TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp: 9 (TestWebKitAPI::TEST): 10 * TestWebKitAPI/Tests/WebKitCocoa/Challenge.mm: 11 (TestWebKitAPI::clientCertServer): 12 * TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm: 13 (TestWebKitAPI::testVideoBytes): 14 (TestWebKitAPI::runVideoTest): 15 (TestWebKitAPI::TEST): 16 * TestWebKitAPI/cocoa/HTTPServer.h: 17 (TestWebKitAPI::HTTPResponse::HTTPResponse): 18 (TestWebKitAPI::HTTPServer::HTTPResponse::HTTPResponse): Deleted. 19 * TestWebKitAPI/cocoa/HTTPServer.mm: 20 (TestWebKitAPI::HTTPServer::RequestData::RequestData): 21 (TestWebKitAPI::appendToVector): 22 (TestWebKitAPI::HTTPServer::parsePath): 23 (TestWebKitAPI::HTTPServer::respondToRequests): 24 (TestWebKitAPI::HTTPResponse::bodyFromString): 25 (TestWebKitAPI::HTTPResponse::serialize): 26 1 27 2021-02-15 John Wilander <wilander@apple.com> 2 28 -
trunk/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp
r272764 r272908 27 27 28 28 #include <WebCore/ParsedContentRange.h> 29 #include <WebCore/ParsedRequestRange.h> 29 30 #include <wtf/text/WTFString.h> 30 31 … … 96 97 } 97 98 99 TEST(WebCore, ParsedRequestRange) 100 { 101 Vector<String> failureCases { 102 { }, 103 "", 104 "abc", 105 "bytes=", 106 "bytes=-", 107 "bytes=abc-", 108 "bytes=1-abc", 109 "bytes=2-1", 110 "bytes=1-", 111 "bytes=-1", 112 "bytes=1-999999999999999999999999" 113 }; 114 for (const auto& input : failureCases) 115 EXPECT_EQ(WTF::nullopt, ParsedRequestRange::parse(input)); 116 117 auto compare = [] (const String& input, Optional<size_t> begin, Optional<size_t> end) { 118 auto range = ParsedRequestRange::parse(input); 119 EXPECT_NE(WTF::nullopt, range); 120 121 }; 122 compare("bytes=1-1", 1, 1); 123 compare("bytes=1-2", 1, 2); 98 124 } 125 126 } -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Challenge.mm
r272764 r272908 590 590 { "/6.png", { longString } }, 591 591 { "/redirectToError", { 301, {{ "Location", "/error" }} } }, 592 { "/error", { HTTP Server::HTTPResponse::TerminateConnection::Yes } },592 { "/error", { HTTPResponse::TerminateConnection::Yes } }, 593 593 }, HTTPServer::Protocol::Https, [] (auto, auto, auto certificateAllowed) { 594 594 certificateAllowed(true); -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/MediaLoading.mm
r272764 r272908 28 28 #import "HTTPServer.h" 29 29 #import "PlatformUtilities.h" 30 #import "TestUIDelegate.h" 30 31 #import "TestWKWebView.h" 31 32 #import <wtf/text/StringConcatenateNumbers.h> … … 117 118 } 118 119 120 const char* videoPlayTestHTML ="<script>" 121 "function createVideoElement() {" 122 "let video = document.createElement('video');" 123 "video.addEventListener('error', ()=>{alert('error')});" 124 "video.addEventListener('playing', ()=>{alert('playing')});" 125 "video.src='video.mp4';" 126 "video.autoplay=1;" 127 "document.body.appendChild(video);" 128 "}" 129 "</script>" 130 "<body onload='createVideoElement()'></body>"; 131 132 static Vector<uint8_t> testVideoBytes() 133 { 134 NSData *data = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"test" withExtension:@"mp4" subdirectory:@"TestWebKitAPI.resources"]]; 135 Vector<uint8_t> vector; 136 vector.append(static_cast<const uint8_t*>(data.bytes), data.length); 137 return vector; 119 138 } 120 139 140 static void runVideoTest(NSURLRequest *request, const char* expectedMessage = "playing") 141 { 142 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 143 configuration.get().mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone; 144 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]); 145 [webView loadRequest:request]; 146 EXPECT_WK_STREQ([webView _test_waitForAlert], expectedMessage); 147 } 148 149 TEST(MediaLoading, RangeRequestSynthesisWithContentLength) 150 { 151 HTTPServer server({ 152 {"/", { videoPlayTestHTML }}, 153 {"/video.mp4", { testVideoBytes() }} 154 }); 155 runVideoTest(server.request()); 156 EXPECT_EQ(server.totalRequests(), 2u); 157 } 158 159 TEST(MediaLoading, RangeRequestSynthesisWithoutContentLength) 160 { 161 size_t totalRequests { 0 }; 162 Function<void(Connection)> respondToRequests; 163 respondToRequests = [&] (Connection connection) { 164 connection.receiveHTTPRequest([&, connection] (Vector<char>&& request) { 165 auto sendResponse = [&, connection] (HTTPResponse response, HTTPResponse::IncludeContentLength includeContentLength) { 166 connection.send(response.serialize(includeContentLength), [&, connection] { 167 respondToRequests(connection); 168 }); 169 }; 170 totalRequests++; 171 auto path = HTTPServer::parsePath(request); 172 if (path == "/") 173 sendResponse({ videoPlayTestHTML }, HTTPResponse::IncludeContentLength::Yes); 174 else if (path == "/video.mp4") 175 sendResponse(testVideoBytes(), HTTPResponse::IncludeContentLength::No); 176 else 177 ASSERT(path.isNull()); 178 }); 179 }; 180 181 HTTPServer server([&](Connection connection) { 182 respondToRequests(connection); 183 }); 184 runVideoTest(server.request(), "error"); 185 EXPECT_EQ(totalRequests, 2u); 186 } 187 188 } // namespace TestWebKitAPI 189 121 190 #endif // ENABLE(VIDEO) && USE(AVFOUNDATION) -
trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h
r272764 r272908 36 36 37 37 class Connection; 38 struct HTTPResponse; 38 39 39 40 class HTTPServer { 40 41 public: 41 struct HTTPResponse;42 42 struct RequestData; 43 43 enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS, Http2 }; … … 54 54 static void respondWithOK(Connection); 55 55 static void respondWithChallengeThenOK(Connection); 56 static String parsePath(const Vector<char>& request); 56 57 57 58 private: … … 82 83 }; 83 84 84 struct HTTP Server::HTTPResponse {85 struct HTTPResponse { 85 86 enum class TerminateConnection { No, Yes }; 86 87 88 HTTPResponse(Vector<uint8_t>&& body) 89 : body(WTFMove(body)) { } 87 90 HTTPResponse(const String& body) 88 : body(body ) { }89 HTTPResponse(HashMap<String, String>&& headerFields, String&& body)91 : body(bodyFromString(body)) { } 92 HTTPResponse(HashMap<String, String>&& headerFields, const String& body) 90 93 : headerFields(WTFMove(headerFields)) 91 , body( WTFMove(body)) { }92 HTTPResponse(unsigned statusCode, HashMap<String, String>&& headerFields = { }, String&& body = { })94 , body(bodyFromString(body)) { } 95 HTTPResponse(unsigned statusCode, HashMap<String, String>&& headerFields = { }, const String& body = { }) 93 96 : statusCode(statusCode) 94 97 , headerFields(WTFMove(headerFields)) 95 , body( WTFMove(body)) { }98 , body(bodyFromString(body)) { } 96 99 HTTPResponse(TerminateConnection terminateConnection) 97 100 : terminateConnection(terminateConnection) { } … … 102 105 HTTPResponse& operator=(const HTTPResponse&) = default; 103 106 HTTPResponse& operator=(HTTPResponse&&) = default; 104 107 108 enum class IncludeContentLength : bool { No, Yes }; 109 Vector<uint8_t> serialize(IncludeContentLength = IncludeContentLength::Yes); 110 static Vector<uint8_t> bodyFromString(const String&); 111 105 112 unsigned statusCode { 200 }; 106 113 HashMap<String, String> headerFields; 107 Stringbody;114 Vector<uint8_t> body; 108 115 TerminateConnection terminateConnection { TerminateConnection::No }; 109 116 }; -
trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm
r272764 r272908 39 39 struct HTTPServer::RequestData : public ThreadSafeRefCounted<RequestData, WTF::DestructionThread::MainRunLoop> { 40 40 RequestData(std::initializer_list<std::pair<String, HTTPResponse>> responses) 41 : requestMap([](std::initializer_list<std::pair<String, HTTP Server::HTTPResponse>> list) {42 HashMap<String, HTTP Server::HTTPResponse> map;41 : requestMap([](std::initializer_list<std::pair<String, HTTPResponse>> list) { 42 HashMap<String, HTTPResponse> map; 43 43 for (auto& pair : list) 44 44 map.add(pair.first, pair.second); … … 213 213 } 214 214 215 static void appendUTF8ToVector(Vector<uint8_t>& vector, const String& string) 216 { 217 auto utf8 = string.utf8(); 218 vector.append(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length()); 219 } 220 221 String HTTPServer::parsePath(const Vector<char>& request) 222 { 223 if (!request.size()) 224 return { }; 225 const char* getPathPrefix = "GET "; 226 const char* postPathPrefix = "POST "; 227 const char* pathSuffix = " HTTP/1.1\r\n"; 228 const char* pathEnd = strnstr(request.data(), pathSuffix, request.size()); 229 ASSERT_WITH_MESSAGE(pathEnd, "HTTPServer assumes request is HTTP 1.1"); 230 size_t pathPrefixLength = 0; 231 if (!memcmp(request.data(), getPathPrefix, strlen(getPathPrefix))) 232 pathPrefixLength = strlen(getPathPrefix); 233 else if (!memcmp(request.data(), postPathPrefix, strlen(postPathPrefix))) 234 pathPrefixLength = strlen(postPathPrefix); 235 ASSERT_WITH_MESSAGE(pathPrefixLength, "HTTPServer assumes request is GET or POST"); 236 size_t pathLength = pathEnd - request.data() - pathPrefixLength; 237 return String(request.data() + pathPrefixLength, pathLength); 238 } 239 215 240 void HTTPServer::respondToRequests(Connection connection, Ref<RequestData> requestData) 216 241 { … … 220 245 requestData->requestCount++; 221 246 222 const char* getPathPrefix = "GET "; 223 const char* postPathPrefix = "POST "; 224 const char* pathSuffix = " HTTP/1.1\r\n"; 225 const char* pathEnd = strnstr(request.data(), pathSuffix, request.size()); 226 ASSERT_WITH_MESSAGE(pathEnd, "HTTPServer assumes request is HTTP 1.1"); 227 size_t pathPrefixLength = 0; 228 if (!memcmp(request.data(), getPathPrefix, strlen(getPathPrefix))) 229 pathPrefixLength = strlen(getPathPrefix); 230 else if (!memcmp(request.data(), postPathPrefix, strlen(postPathPrefix))) 231 pathPrefixLength = strlen(postPathPrefix); 232 ASSERT_WITH_MESSAGE(pathPrefixLength, "HTTPServer assumes request is GET or POST"); 233 size_t pathLength = pathEnd - request.data() - pathPrefixLength; 234 String path(request.data() + pathPrefixLength, pathLength); 247 auto path = parsePath(request); 235 248 ASSERT_WITH_MESSAGE(requestData->requestMap.contains(path), "This HTTPServer does not know how to respond to a request for %s", path.utf8().data()); 236 249 … … 238 251 if (response.terminateConnection == HTTPResponse::TerminateConnection::Yes) 239 252 return connection.terminate(); 240 StringBuilder responseBuilder; 241 responseBuilder.append("HTTP/1.1 ", response.statusCode, ' ', statusText(response.statusCode), "\r\n"); 242 responseBuilder.append("Content-Length: ", response.body.length(), "\r\n"); 243 for (auto& pair : response.headerFields) 244 responseBuilder.append(pair.key, ": ", pair.value, "\r\n"); 245 responseBuilder.append("\r\n"); 246 responseBuilder.append(response.body); 247 connection.send(responseBuilder.toString(), [connection, requestData] { 253 254 connection.send(response.serialize(), [connection, requestData] { 248 255 respondToRequests(connection, requestData); 249 256 }); … … 333 340 Util::run(&cancelled); 334 341 m_connection = nullptr; 342 } 343 344 Vector<uint8_t> HTTPResponse::bodyFromString(const String& string) 345 { 346 Vector<uint8_t> vector; 347 appendUTF8ToVector(vector, string); 348 return vector; 349 } 350 351 Vector<uint8_t> HTTPResponse::serialize(IncludeContentLength includeContentLength) 352 { 353 StringBuilder responseBuilder; 354 responseBuilder.append("HTTP/1.1 ", statusCode, ' ', statusText(statusCode), "\r\n"); 355 if (includeContentLength == IncludeContentLength::Yes) 356 responseBuilder.append("Content-Length: ", body.size(), "\r\n"); 357 for (auto& pair : headerFields) 358 responseBuilder.append(pair.key, ": ", pair.value, "\r\n"); 359 responseBuilder.append("\r\n"); 360 361 Vector<uint8_t> bytesToSend; 362 appendUTF8ToVector(bytesToSend, responseBuilder.toString()); 363 bytesToSend.appendVector(body); 364 return bytesToSend; 335 365 } 336 366
Note: See TracChangeset
for help on using the changeset viewer.