Diff
Added: trunk/LayoutTests/http/tests/xmlhttprequest/blob-request-byte-range-expected.txt (0 => 195764)
--- trunk/LayoutTests/http/tests/xmlhttprequest/blob-request-byte-range-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/blob-request-byte-range-expected.txt 2016-01-28 19:17:17 UTC (rev 195764)
@@ -0,0 +1,5 @@
+Test an XMLHttpRequest of a Blob URL requesting a byte-range responds appropriately.
+
+PASS: "req.status" == "206"
+PASS: "req.getResponseHeader("Content-Range")" == "bytes 1-2/4"
+
Added: trunk/LayoutTests/http/tests/xmlhttprequest/blob-request-byte-range.html (0 => 195764)
--- trunk/LayoutTests/http/tests/xmlhttprequest/blob-request-byte-range.html (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/blob-request-byte-range.html 2016-01-28 19:17:17 UTC (rev 195764)
@@ -0,0 +1,45 @@
+<html>
+<body>
+<p>Test an XMLHttpRequest of a Blob URL requesting a byte-range responds appropriately.</p>
+<pre id="console"></pre>
+<script>
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+
+function log(text)
+{
+ var console = document.getElementById('console');
+ console.appendChild(document.createTextNode(text + '\n'));
+}
+
+function test(expect, actual)
+{
+ var result = eval(actual);
+ if (expect == result)
+ log(`PASS: "${ actual }" == "${ expect }"`);
+ else
+ log(`FAIL: "${ actual }" EXPECT "${ expect }" GOT "${ result }"`);
+}
+
+var array = new Int8Array([0, 1, 2, 3]);
+var blob = new Blob(array);
+var url = ""
+
+var req = new XMLHttpRequest;
+req.responseType = 'blob';
+req.open('GET', url);
+req.setRequestHeader('Range', 'bytes=1-2');
+req._onreadystatechange_ = function() {
+ if (req.readyState == 4) {
+ test(206, 'req.status');
+ test('bytes 1-2/4', 'req.getResponseHeader("Content-Range")');
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+};
+req.send();
+
+</script>
+</body>
Modified: trunk/Source/WebCore/CMakeLists.txt (195763 => 195764)
--- trunk/Source/WebCore/CMakeLists.txt 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/CMakeLists.txt 2016-01-28 19:17:17 UTC (rev 195764)
@@ -2331,6 +2331,7 @@
platform/network/HTTPParsers.cpp
platform/network/MIMEHeader.cpp
platform/network/NetworkStateNotifier.cpp
+ platform/network/ParsedContentRange.cpp
platform/network/ParsedContentType.cpp
platform/network/ProtectionSpaceBase.cpp
platform/network/ProxyServer.cpp
Modified: trunk/Source/WebCore/ChangeLog (195763 => 195764)
--- trunk/Source/WebCore/ChangeLog 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/ChangeLog 2016-01-28 19:17:17 UTC (rev 195764)
@@ -1,3 +1,63 @@
+2016-01-08 Jer Noble <jer.no...@apple.com>
+
+ Custom protocol loading through AVFoundation does not support byte-range requests.
+ https://bugs.webkit.org/show_bug.cgi?id=152919
+ <rdar://problem/23664657>
+
+ Reviewed by Alex Christensen.
+
+ Tests: http/tests/xmlhttprequest/blob-request-byte-range.html
+ TestWebkitAPI/Tests/WebCore/ParsedContentRange.cpp
+
+ When loading data through the AVAssetResourceLoaderDelegateProtocol, AVFoundation will issue
+ requests for specific byte-ranges by adding a "Range:" HTTP header to the NSURLRequest it
+ passes to the delegate. WebCore ignores this header, loads the entire resource, and replies
+ to the callback with the requested subset of the entire resource.
+
+ For byte-range requests near the end of a resource, this is inefficient, as the entire
+ resource up to, and including, the requested range must be loaded before any data can be
+ returned. Explicitly handle byte-range requests by creating a CachedResourceRequest with the
+ underlying NSURLRequest (which includes the "Range:" header) rather than just the request's
+ URL. BlobResourceHandle must be modified to add the "Content-Range:" response header to the
+ ResourceResponse.
+
+ To facilitate both generating and parsing the "Content-Range:" header, add a new
+ ParsedContentRange class for use by ResourceResponse and its clients. This class provides
+ methods both for parsing a "Content-Range" header value string, and for generating the
+ header value from elemental values.
+
+ * platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm:
+ (WebCore::WebCoreAVFResourceLoader::startLoading):
+ (WebCore::WebCoreAVFResourceLoader::responseReceived):
+ (WebCore::WebCoreAVFResourceLoader::fulfillRequestWithResource):
+ * platform/network/BlobResourceHandle.cpp:
+ (WebCore::BlobResourceHandle::BlobResourceHandle):
+ (WebCore::BlobResourceHandle::didGetSize):
+ (WebCore::BlobResourceHandle::seek):
+ (WebCore::BlobResourceHandle::notifyResponseOnSuccess):
+ * platform/network/BlobResourceHandle.h:
+ * platform/network/HTTPHeaderNames.in:
+ * platform/network/ParsedContentRange.cpp: Added.
+ (WebCore::areContentRangeValuesValid):
+ (WebCore::parseContentRange):
+ (WebCore::ParsedContentRange::ParsedContentRange):
+ (WebCore::ParsedContentRange::headerValue):
+ * platform/network/ParsedContentRange.h: Added.
+ (WebCore::ParsedContentRange::ParsedContentRange):
+ (WebCore::ParsedContentRange::isValid):
+ (WebCore::ParsedContentRange::firstBytePosition):
+ (WebCore::ParsedContentRange::lastBytePosition):
+ (WebCore::ParsedContentRange::instanceLength):
+ * platform/network/ResourceResponseBase.cpp:
+ (WebCore::ResourceResponseBase::updateHeaderParsedState):
+ (WebCore::parseContentRangeInHeader):
+ (WebCore::ResourceResponseBase::contentRange):
+ * platform/network/ResourceResponseBase.h:
+ * CMakeLists.txt:
+ * WebCore.vcxproj/WebCore.vcxproj:
+ * WebCore.vcxproj/WebCore.vcxproj.filters:
+ * WebCore.xcodeproj/project.pbxproj:
+
2016-01-28 Chris Dumez <cdu...@apple.com>
Storage interface's attributes / operations should be enumerable
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (195763 => 195764)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2016-01-28 19:17:17 UTC (rev 195764)
@@ -8886,6 +8886,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="..\platform\network\ParsedContentRange.cpp" />
<ClCompile Include="..\platform\network\ParsedContentType.cpp" />
<ClCompile Include="..\platform\network\ProtectionSpaceBase.cpp" />
<ClCompile Include="..\platform\network\ProxyServer.cpp" />
@@ -21352,6 +21353,7 @@
<ClInclude Include="..\platform\network\NetworkingContext.h" />
<ClInclude Include="..\platform\network\NetworkStateNotifier.h" />
<ClInclude Include="..\platform\network\NetworkStorageSession.h" />
+ <ClInclude Include="..\platform\network\ParsedContentRange.h" />
<ClInclude Include="..\platform\network\ParsedContentType.h" />
<ClInclude Include="..\platform\network\PlatformCookieJar.h" />
<ClInclude Include="..\platform\network\ProtectionSpace.h" />
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (195763 => 195764)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2016-01-28 19:17:17 UTC (rev 195764)
@@ -1772,6 +1772,9 @@
<ClCompile Include="..\platform\network\NetworkStorageSessionStub.cpp">
<Filter>platform\network</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\network\ParsedContentRange.cpp">
+ <Filter>platform\network</Filter>
+ </ClCompile>
<ClCompile Include="..\platform\network\ParsedContentType.cpp">
<Filter>platform\network</Filter>
</ClCompile>
@@ -8779,6 +8782,9 @@
<ClInclude Include="..\platform\network\NetworkStorageSession.h">
<Filter>platform\network</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\network\ParsedContenRange.h">
+ <Filter>platform\network</Filter>
+ </ClInclude>
<ClInclude Include="..\platform\network\ParsedContentType.h">
<Filter>platform\network</Filter>
</ClInclude>
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (195763 => 195764)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-01-28 19:17:17 UTC (rev 195764)
@@ -6097,6 +6097,8 @@
CDC979F51C498C0900DB50D4 /* WebCoreNSErrorExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC979F31C498C0900DB50D4 /* WebCoreNSErrorExtras.h */; };
CDCA82961679100F00875714 /* TextTrackRepresentationIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDCA82941679100F00875714 /* TextTrackRepresentationIOS.mm */; };
CDCA98EB18B2C8EB00C12FF9 /* CDMPrivateMediaPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCA98EA18B2C8EB00C12FF9 /* CDMPrivateMediaPlayer.cpp */; };
+ CDCD41E71C3DDB0900965D99 /* ParsedContentRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCD41E51C3DDB0900965D99 /* ParsedContentRange.cpp */; };
+ CDCD41E81C3DDB0A00965D99 /* ParsedContentRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CDCD41E61C3DDB0900965D99 /* ParsedContentRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDCFABBD18C0AF78006F8450 /* SelectionSubtreeRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = CDCFABBB18C0AE31006F8450 /* SelectionSubtreeRoot.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDCFABBE18C0AF84006F8450 /* SelectionSubtreeRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCFABBC18C0AF19006F8450 /* SelectionSubtreeRoot.cpp */; };
CDD525D7145B6DD0008D204D /* JSHTMLMediaElementCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF65CCC145B6AFE00C4C7AA /* JSHTMLMediaElementCustom.cpp */; };
@@ -14009,6 +14011,8 @@
CDCA82941679100F00875714 /* TextTrackRepresentationIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextTrackRepresentationIOS.mm; sourceTree = "<group>"; };
CDCA98E918B2C8D000C12FF9 /* CDMPrivateMediaPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMPrivateMediaPlayer.h; sourceTree = "<group>"; };
CDCA98EA18B2C8EB00C12FF9 /* CDMPrivateMediaPlayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDMPrivateMediaPlayer.cpp; sourceTree = "<group>"; };
+ CDCD41E51C3DDB0900965D99 /* ParsedContentRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParsedContentRange.cpp; sourceTree = "<group>"; };
+ CDCD41E61C3DDB0900965D99 /* ParsedContentRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParsedContentRange.h; sourceTree = "<group>"; };
CDCE5CD014633BC900D47CCA /* EventTargetFactory.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EventTargetFactory.in; sourceTree = "<group>"; };
CDCFABBB18C0AE31006F8450 /* SelectionSubtreeRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionSubtreeRoot.h; sourceTree = "<group>"; };
CDCFABBC18C0AF19006F8450 /* SelectionSubtreeRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionSubtreeRoot.cpp; sourceTree = "<group>"; };
@@ -17583,6 +17587,8 @@
1A7FA61A0DDA3BBE0028F8A5 /* NetworkStateNotifier.cpp */,
1A7FA6180DDA3B3A0028F8A5 /* NetworkStateNotifier.h */,
E13EF3421684ECF40034C83F /* NetworkStorageSession.h */,
+ CDCD41E51C3DDB0900965D99 /* ParsedContentRange.cpp */,
+ CDCD41E61C3DDB0900965D99 /* ParsedContentRange.h */,
447958021643B47B001E0A7F /* ParsedContentType.cpp */,
447958031643B47B001E0A7F /* ParsedContentType.h */,
51B454E91B4DAE7D0085EAA6 /* PingHandle.h */,
@@ -25671,6 +25677,7 @@
939885C408B7E3D100E707C4 /* EventNames.h in Headers */,
8F67561B1288B17B0047ACA3 /* EventQueue.h in Headers */,
E0FEF372B17C53EAC1C1FBEE /* EventSource.h in Headers */,
+ CDCD41E81C3DDB0A00965D99 /* ParsedContentRange.h in Headers */,
E12EDB7B0B308A78002704B6 /* EventTarget.h in Headers */,
97AA3CA5145237CC003E1DA6 /* EventTargetHeaders.h in Headers */,
97AA3CA6145237CC003E1DA6 /* EventTargetInterfaces.h in Headers */,
@@ -29584,6 +29591,7 @@
A454424A119B3661009BE912 /* HTMLMeterElement.cpp in Sources */,
A8CFF7A90A156978000A4234 /* HTMLModElement.cpp in Sources */,
A8DF3FD5097FA0FC0052981B /* HTMLNameCollection.cpp in Sources */,
+ CDCD41E71C3DDB0900965D99 /* ParsedContentRange.cpp in Sources */,
A8D06B3A0A265DCD005E7203 /* HTMLNames.cpp in Sources */,
A871D45B0A127CBC00B12A68 /* HTMLObjectElement.cpp in Sources */,
A8EA79FB0A1916DF00A8EF5F /* HTMLOListElement.cpp in Sources */,
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm (195763 => 195764)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm 2016-01-28 19:17:17 UTC (rev 195764)
@@ -65,10 +65,10 @@
if (m_resource || !m_parent)
return;
- URL requestURL = [[m_avRequest.get() request] URL];
+ NSURLRequest *nsRequest = [m_avRequest.get() request];
// ContentSecurityPolicyImposition::DoPolicyCheck is a placeholder value. It does not affect the request since Content Security Policy does not apply to raw resources.
- CachedResourceRequest request(ResourceRequest(requestURL), ResourceLoaderOptions(SendCallbacks, DoNotSniffContent, BufferData, DoNotAllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, ClientDidNotRequestCredentials, DoSecurityCheck, UseDefaultOriginRestrictionsForType, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::DoPolicyCheck, DefersLoadingPolicy::AllowDefersLoading));
+ CachedResourceRequest request(nsRequest, ResourceLoaderOptions(SendCallbacks, DoNotSniffContent, BufferData, DoNotAllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, ClientDidNotRequestCredentials, DoSecurityCheck, UseDefaultOriginRestrictionsForType, DoNotIncludeCertificateInfo, ContentSecurityPolicyImposition::DoPolicyCheck, DefersLoadingPolicy::AllowDefersLoading));
request.mutableResourceRequest().setPriority(ResourceLoadPriority::Low);
CachedResourceLoader* loader = m_parent->player()->cachedResourceLoader();
@@ -76,7 +76,7 @@
if (m_resource)
m_resource->addClient(this);
else {
- LOG_ERROR("Failed to start load for media at url %s", requestURL.string().ascii().data());
+ LOG_ERROR("Failed to start load for media at url %s", [[[nsRequest URL] absoluteString] UTF8String]);
[m_avRequest.get() finishLoadingWithError:0];
}
}
@@ -101,8 +101,8 @@
void WebCoreAVFResourceLoader::responseReceived(CachedResource* resource, const ResourceResponse& response)
{
+ ASSERT(resource);
ASSERT(resource == m_resource);
- UNUSED_PARAM(resource);
int status = response.httpStatusCode();
if (status && (status < 200 || status > 299)) {
@@ -114,7 +114,9 @@
String uti = UTIFromMIMEType(response.mimeType().createCFString().get()).get();
[contentInfo setContentType:uti];
- [contentInfo setContentLength:response.expectedContentLength()];
+
+ ParsedContentRange& contentRange = resource->response().contentRange();
+ [contentInfo setContentLength:contentRange.isValid() ? contentRange.instanceLength() : response.expectedContentLength()];
[contentInfo setByteRangeAccessSupported:YES];
if (![m_avRequest dataRequest]) {
@@ -147,6 +149,7 @@
void WebCoreAVFResourceLoader::fulfillRequestWithResource(CachedResource* resource)
{
+ ASSERT(resource);
ASSERT(resource == m_resource);
AVAssetResourceLoadingDataRequest* dataRequest = [m_avRequest dataRequest];
if (!dataRequest)
@@ -156,6 +159,11 @@
if (!data)
return;
+ NSUInteger responseOffset = 0;
+ ParsedContentRange contentRange = resource->response().contentRange();
+ if (contentRange.isValid())
+ responseOffset = static_cast<NSUInteger>(contentRange.firstBytePosition());
+
// Check for possible unsigned overflow.
ASSERT([dataRequest currentOffset] >= [dataRequest requestedOffset]);
ASSERT([dataRequest requestedLength] >= ([dataRequest currentOffset] - [dataRequest requestedOffset]));
@@ -163,11 +171,11 @@
NSUInteger remainingLength = [dataRequest requestedLength] - static_cast<NSUInteger>([dataRequest currentOffset] - [dataRequest requestedOffset]);
do {
// Check to see if there is any data available in the buffer to fulfill the data request.
- if (data->size() <= [dataRequest currentOffset])
+ if (data->size() <= [dataRequest currentOffset] - responseOffset)
return;
const char* someData;
- NSUInteger receivedLength = data->getSomeData(someData, static_cast<unsigned>([dataRequest currentOffset]));
+ NSUInteger receivedLength = data->getSomeData(someData, static_cast<unsigned>([dataRequest currentOffset] - responseOffset));
// Create an NSData with only as much of the received data as necessary to fulfill the request.
NSUInteger length = MIN(receivedLength, remainingLength);
Modified: trunk/Source/WebCore/platform/network/BlobResourceHandle.cpp (195763 => 195764)
--- trunk/Source/WebCore/platform/network/BlobResourceHandle.cpp 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/platform/network/BlobResourceHandle.cpp 2016-01-28 19:17:17 UTC (rev 195764)
@@ -38,6 +38,7 @@
#include "FileSystem.h"
#include "HTTPHeaderNames.h"
#include "HTTPParsers.h"
+#include "ParsedContentRange.h"
#include "URL.h"
#include "ResourceError.h"
#include "ResourceHandleClient.h"
@@ -50,7 +51,6 @@
namespace WebCore {
static const unsigned bufferSize = 512 * 1024;
-static const long long positionNotSpecified = -1;
static const int httpOK = 200;
static const int httpPartialContent = 206;
@@ -159,16 +159,6 @@
: ResourceHandle(0, request, client, false, false)
, m_blobData(blobData)
, m_async(async)
- , m_errorCode(0)
- , m_aborted(false)
- , m_rangeOffset(positionNotSpecified)
- , m_rangeEnd(positionNotSpecified)
- , m_rangeSuffixLength(positionNotSpecified)
- , m_totalRemainingSize(0)
- , m_currentItemReadSize(0)
- , m_sizeItemCount(0)
- , m_readItemCount(0)
- , m_fileOpened(false)
{
if (m_async)
m_asyncStream = std::make_unique<AsyncFileStream>(*this);
@@ -300,6 +290,7 @@
m_itemLengthList.append(size);
// Count the size.
+ m_totalSize += size;
m_totalRemainingSize += size;
m_sizeItemCount++;
@@ -312,13 +303,13 @@
ASSERT(isMainThread());
// Convert from the suffix length to the range.
- if (m_rangeSuffixLength != positionNotSpecified) {
+ if (m_rangeSuffixLength != kPositionNotSpecified) {
m_rangeOffset = m_totalRemainingSize - m_rangeSuffixLength;
m_rangeEnd = m_rangeOffset + m_rangeSuffixLength - 1;
}
// Bail out if the range is not provided.
- if (m_rangeOffset == positionNotSpecified)
+ if (m_rangeOffset == kPositionNotSpecified)
return;
// Skip the initial items that are not in the range.
@@ -330,7 +321,7 @@
m_currentItemReadSize = offset;
// Adjust the total remaining size in order not to go beyond the range.
- if (m_rangeEnd != positionNotSpecified) {
+ if (m_rangeEnd != kPositionNotSpecified) {
long long rangeSize = m_rangeEnd - m_rangeOffset + 1;
if (m_totalRemainingSize > rangeSize)
m_totalRemainingSize = rangeSize;
@@ -583,10 +574,12 @@
{
ASSERT(isMainThread());
- bool isRangeRequest = m_rangeOffset != positionNotSpecified;
+ bool isRangeRequest = m_rangeOffset != kPositionNotSpecified;
ResourceResponse response(firstRequest().url(), m_blobData->contentType(), m_totalRemainingSize, String());
response.setHTTPStatusCode(isRangeRequest ? httpPartialContent : httpOK);
response.setHTTPStatusText(isRangeRequest ? httpPartialContentText : httpOKText);
+ if (isRangeRequest)
+ response.setHTTPHeaderField(HTTPHeaderName::ContentRange, ParsedContentRange(m_rangeOffset, m_rangeEnd, m_totalSize).headerValue());
// FIXME: If a resource identified with a blob: URL is a File object, user agents must use that file's name attribute,
// as if the response had a Content-Disposition header with the filename parameter set to the File's name attribute.
// Notably, this will affect a name suggested in "File Save As".
Modified: trunk/Source/WebCore/platform/network/BlobResourceHandle.h (195763 => 195764)
--- trunk/Source/WebCore/platform/network/BlobResourceHandle.h 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/platform/network/BlobResourceHandle.h 2016-01-28 19:17:17 UTC (rev 195764)
@@ -90,22 +90,25 @@
void notifyFail(int errorCode);
void notifyFinish();
+ enum { kPositionNotSpecified = -1 };
+
RefPtr<BlobData> m_blobData;
bool m_async;
std::unique_ptr<AsyncFileStream> m_asyncStream; // For asynchronous loading.
std::unique_ptr<FileStream> m_stream; // For synchronous loading.
Vector<char> m_buffer;
Vector<long long> m_itemLengthList;
- int m_errorCode;
- bool m_aborted;
- long long m_rangeOffset;
- long long m_rangeEnd;
- long long m_rangeSuffixLength;
- long long m_totalRemainingSize;
- long long m_currentItemReadSize;
- unsigned m_sizeItemCount;
- unsigned m_readItemCount;
- bool m_fileOpened;
+ int m_errorCode { 0 };
+ bool m_aborted { false };
+ long long m_rangeOffset { kPositionNotSpecified };
+ long long m_rangeEnd { kPositionNotSpecified };
+ long long m_rangeSuffixLength { kPositionNotSpecified };
+ long long m_totalSize { 0 };
+ long long m_totalRemainingSize { 0 };
+ long long m_currentItemReadSize { 0 };
+ unsigned m_sizeItemCount { 0 };
+ unsigned m_readItemCount { 0 };
+ bool m_fileOpened { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/network/HTTPHeaderNames.in (195763 => 195764)
--- trunk/Source/WebCore/platform/network/HTTPHeaderNames.in 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/platform/network/HTTPHeaderNames.in 2016-01-28 19:17:17 UTC (rev 195764)
@@ -49,6 +49,7 @@
Content-Security-Policy-Report-Only
Content-Type
Content-Transfer-Encoding
+Content-Range
Cookie
Cookie2
Date
Added: trunk/Source/WebCore/platform/network/ParsedContentRange.cpp (0 => 195764)
--- trunk/Source/WebCore/platform/network/ParsedContentRange.cpp (rev 0)
+++ trunk/Source/WebCore/platform/network/ParsedContentRange.cpp 2016-01-28 19:17:17 UTC (rev 195764)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+#include "ParsedContentRange.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+static bool areContentRangeValuesValid(int64_t firstBytePosition, int64_t lastBytePosition, int64_t instanceLength)
+{
+ // From <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html>
+ // 14.16 Content-Range
+ // A byte-content-range-spec with a byte-range-resp-spec whose last- byte-pos value is less than its first-byte-pos value,
+ // or whose instance-length value is less than or equal to its last-byte-pos value, is invalid.
+ if (firstBytePosition < 0)
+ return false;
+
+ if (lastBytePosition < firstBytePosition)
+ return false;
+
+ if (instanceLength == ParsedContentRange::UnknownLength)
+ return true;
+
+ return lastBytePosition < instanceLength;
+}
+
+static bool parseContentRange(const String& headerValue, int64_t& firstBytePosition, int64_t& lastBytePosition, int64_t& instanceLength)
+{
+ // From <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html>
+ // 14.16 Content-Range
+ //
+ // Content-Range = "Content-Range" ":" content-range-spec
+ // content-range-spec = byte-content-range-spec
+ // byte-content-range-spec = bytes-unit SP
+ // byte-range-resp-spec "/"
+ // ( instance-length | "*" )
+ // byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
+ // | "*"
+ // instance-length = 1*DIGIT
+
+ static const char* prefix = "bytes ";
+ static const size_t prefixLength = 6;
+
+ if (!headerValue.startsWith(prefix))
+ return false;
+
+ size_t byteSeparatorTokenLoc = headerValue.find('-', prefixLength);
+ if (byteSeparatorTokenLoc == notFound)
+ return false;
+
+ size_t instanceLengthSeparatorToken = headerValue.find('/', byteSeparatorTokenLoc + 1);
+ if (instanceLengthSeparatorToken == notFound)
+ return false;
+
+ bool isOk = true;
+ String firstByteString = headerValue.substring(prefixLength, byteSeparatorTokenLoc - prefixLength);
+ if (!firstByteString.isAllSpecialCharacters<isASCIIDigit>())
+ return false;
+
+ firstBytePosition = firstByteString.toInt64Strict(&isOk);
+ if (!isOk)
+ return false;
+
+ String lastByteString = headerValue.substring(byteSeparatorTokenLoc + 1, instanceLengthSeparatorToken - (byteSeparatorTokenLoc + 1));
+ if (!lastByteString.isAllSpecialCharacters<isASCIIDigit>())
+ return false;
+
+ lastBytePosition = lastByteString.toInt64Strict(&isOk);
+ if (!isOk)
+ return false;
+
+ String instanceString = headerValue.substring(instanceLengthSeparatorToken + 1);
+ if (instanceString == "*")
+ instanceLength = ParsedContentRange::UnknownLength;
+ else {
+ if (!instanceString.isAllSpecialCharacters<isASCIIDigit>())
+ return false;
+
+ instanceLength = instanceString.toInt64Strict(&isOk);
+ if (!isOk)
+ return false;
+ }
+
+ return areContentRangeValuesValid(firstBytePosition, lastBytePosition, instanceLength);
+}
+
+ParsedContentRange::ParsedContentRange(const String& headerValue)
+{
+ m_isValid = parseContentRange(headerValue, m_firstBytePosition, m_lastBytePosition, m_instanceLength);
+}
+
+ParsedContentRange::ParsedContentRange(int64_t firstBytePosition, int64_t lastBytePosition, int64_t instanceLength)
+ : m_firstBytePosition(firstBytePosition)
+ , m_lastBytePosition(lastBytePosition)
+ , m_instanceLength(instanceLength)
+{
+ m_isValid = areContentRangeValuesValid(m_firstBytePosition, m_lastBytePosition, m_instanceLength);
+}
+
+String ParsedContentRange::headerValue() const
+{
+ if (!m_isValid)
+ return String();
+ if (m_instanceLength == UnknownLength)
+ return String::format("bytes %" PRId64 "-%" PRId64 "/*", m_firstBytePosition, m_lastBytePosition);
+ return String::format("bytes %" PRId64 "-%" PRId64 "/%" PRId64, m_firstBytePosition, m_lastBytePosition, m_instanceLength);
+}
+
+}
Added: trunk/Source/WebCore/platform/network/ParsedContentRange.h (0 => 195764)
--- trunk/Source/WebCore/platform/network/ParsedContentRange.h (rev 0)
+++ trunk/Source/WebCore/platform/network/ParsedContentRange.h 2016-01-28 19:17:17 UTC (rev 195764)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef ParsedContentRange_h
+#define ParsedContentRange_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class ParsedContentRange {
+public:
+ WEBCORE_EXPORT explicit ParsedContentRange(const String&);
+ WEBCORE_EXPORT ParsedContentRange() { }
+ WEBCORE_EXPORT ParsedContentRange(int64_t firstBytePosition, int64_t lastBytePosition, int64_t instanceLength);
+
+ WEBCORE_EXPORT bool isValid() const { return m_isValid; }
+ int64_t firstBytePosition() const { return m_firstBytePosition; }
+ int64_t lastBytePosition() const { return m_lastBytePosition; }
+ int64_t instanceLength() const { return m_instanceLength; }
+
+ WEBCORE_EXPORT String headerValue() const;
+
+ enum { UnknownLength = std::numeric_limits<int64_t>::max() };
+
+private:
+ template<typename T> static bool isPositive(T);
+
+ bool m_isValid { false };
+ int64_t m_firstBytePosition { 0 };
+ int64_t m_lastBytePosition { 0 };
+ int64_t m_instanceLength { UnknownLength };
+};
+
+}
+
+#endif
Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp (195763 => 195764)
--- trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp 2016-01-28 19:17:17 UTC (rev 195764)
@@ -30,6 +30,7 @@
#include "CacheValidation.h"
#include "HTTPHeaderNames.h"
#include "HTTPParsers.h"
+#include "ParsedContentRange.h"
#include "ResourceResponse.h"
#include <wtf/CurrentTime.h>
#include <wtf/MathExtras.h>
@@ -300,6 +301,10 @@
m_haveParsedLastModifiedHeader = false;
break;
+ case HTTPHeaderName::ContentRange:
+ m_haveParsedContentRangeHeader = false;
+ break;
+
default:
break;
}
@@ -461,6 +466,27 @@
return m_lastModified;
}
+static ParsedContentRange parseContentRangeInHeader(const HTTPHeaderMap& headers)
+{
+ String contentRangeValue = headers.get(HTTPHeaderName::ContentRange);
+ if (contentRangeValue.isEmpty())
+ return ParsedContentRange();
+
+ return ParsedContentRange(contentRangeValue);
+}
+
+ParsedContentRange& ResourceResponseBase::contentRange() const
+{
+ lazyInit(CommonFieldsOnly);
+
+ if (!m_haveParsedContentRangeHeader) {
+ m_contentRange = parseContentRangeInHeader(m_httpHeaderFields);
+ m_haveParsedContentRangeHeader = true;
+ }
+
+ return m_contentRange;
+}
+
bool ResourceResponseBase::isAttachment() const
{
lazyInit(AllFields);
Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.h (195763 => 195764)
--- trunk/Source/WebCore/platform/network/ResourceResponseBase.h 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.h 2016-01-28 19:17:17 UTC (rev 195764)
@@ -30,6 +30,7 @@
#include "CacheValidation.h"
#include "CertificateInfo.h"
#include "HTTPHeaderMap.h"
+#include "ParsedContentRange.h"
#include "ResourceLoadTiming.h"
#include "URL.h"
@@ -110,6 +111,7 @@
WEBCORE_EXPORT Optional<std::chrono::microseconds> age() const;
WEBCORE_EXPORT Optional<std::chrono::system_clock::time_point> expires() const;
WEBCORE_EXPORT Optional<std::chrono::system_clock::time_point> lastModified() const;
+ ParsedContentRange& contentRange() const;
// This is primarily for testing support. It is not necessarily accurate in all scenarios.
enum class Source { Unknown, Network, DiskCache, DiskCacheAfterValidation, MemoryCache, MemoryCacheAfterValidation };
@@ -175,6 +177,7 @@
mutable Optional<std::chrono::system_clock::time_point> m_date;
mutable Optional<std::chrono::system_clock::time_point> m_expires;
mutable Optional<std::chrono::system_clock::time_point> m_lastModified;
+ mutable ParsedContentRange m_contentRange;
mutable CacheControlDirectives m_cacheControlDirectives;
mutable bool m_haveParsedCacheControlHeader { false };
@@ -182,6 +185,7 @@
mutable bool m_haveParsedDateHeader { false };
mutable bool m_haveParsedExpiresHeader { false };
mutable bool m_haveParsedLastModifiedHeader { false };
+ mutable bool m_haveParsedContentRangeHeader { false };
Source m_source { Source::Unknown };
};
Modified: trunk/Tools/ChangeLog (195763 => 195764)
--- trunk/Tools/ChangeLog 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Tools/ChangeLog 2016-01-28 19:17:17 UTC (rev 195764)
@@ -1,3 +1,20 @@
+2016-01-12 Jer Noble <jer.no...@apple.com>
+
+ Custom protocol loading through AVFoundation does not support byte-range requests.
+ https://bugs.webkit.org/show_bug.cgi?id=152919
+ <rdar://problem/23664657>
+
+ Reviewed by Alex Christensen.
+
+ Add tests for new ParsedContntRange class.
+
+ * TestWebKitAPI/PlatformWin.cmake:
+ * TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj:
+ * TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj.filters:
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp: Added.
+ (TestWebKitAPI::TEST):
+
2016-01-28 Konstantin Tokarev <annu...@yandex.ru>
Use isAnyWindows() instead of isCygwin() || isWindows() in Perl scripts.
Modified: trunk/Tools/TestWebKitAPI/PlatformWin.cmake (195763 => 195764)
--- trunk/Tools/TestWebKitAPI/PlatformWin.cmake 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Tools/TestWebKitAPI/PlatformWin.cmake 2016-01-28 19:17:17 UTC (rev 195764)
@@ -41,6 +41,7 @@
${TESTWEBKITAPI_DIR}/Tests/WebCore/CalculationValue.cpp
${TESTWEBKITAPI_DIR}/Tests/WebCore/CSSParser.cpp
${TESTWEBKITAPI_DIR}/Tests/WebCore/LayoutUnit.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/ParsedContentRange.cpp
${TESTWEBKITAPI_DIR}/Tests/WebCore/TimeRanges.cpp
${TESTWEBKITAPI_DIR}/Tests/WebCore/URL.cpp
)
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj (195763 => 195764)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj 2016-01-28 19:17:17 UTC (rev 195764)
@@ -295,6 +295,7 @@
<ClCompile Include="..\Tests\WebCore\CalculationValue.cpp" />
<ClCompile Include="..\Tests\WebCore\CSSParser.cpp" />
<ClCompile Include="..\Tests\WebCore\LayoutUnit.cpp" />
+ <ClCompile Include="..\Tests\WebCore\ParsedContentRange.cpp" />
<ClCompile Include="..\Tests\WebCore\TimeRanges.cpp" />
<ClCompile Include="..\Tests\WebCore\URL.cpp" />
<ClCompile Include="..\Tests\WebCore\win\BitmapImage.cpp">
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj.filters (195763 => 195764)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj.filters 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj.filters 2016-01-28 19:17:17 UTC (rev 195764)
@@ -157,6 +157,9 @@
<ClCompile Include="..\Tests\WebCore\CalculationValue.cpp">
<Filter>Tests\WebCore</Filter>
</ClCompile>
+ <ClCompile Include="..\Tests\WebCore\ParsedContentRange.cpp">
+ <Filter>Tests\WebCore</Filter>
+ </ClCompile>
<ClCompile Include="..\Tests\WebCore\TimeRanges.cpp">
<Filter>Tests\WebCore</Filter>
</ClCompile>
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (195763 => 195764)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2016-01-28 19:07:40 UTC (rev 195763)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2016-01-28 19:17:17 UTC (rev 195764)
@@ -313,6 +313,7 @@
C540F784152E5A9A00A40C8C /* verboseMarkup.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C540F783152E5A7800A40C8C /* verboseMarkup.html */; };
C54237F116B8957D00E638FC /* PasteboardNotifications_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C54237ED16B8955800E638FC /* PasteboardNotifications_Bundle.cpp */; };
C5E1AFFE16B221F1006CC1F2 /* execCopy.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C5E1AFFD16B22179006CC1F2 /* execCopy.html */; };
+ CD225C081C45A69200140761 /* ParsedContentRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD225C071C45A69200140761 /* ParsedContentRange.cpp */; };
CD59F53419E9110D00CF1835 /* file-with-mse.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CD59F53219E910AA00CF1835 /* file-with-mse.html */; };
CD59F53519E9110D00CF1835 /* test-mse.mp4 in Copy Resources */ = {isa = PBXBuildFile; fileRef = CD59F53319E910BC00CF1835 /* test-mse.mp4 */; };
CDBFCC451A9FF45300A7B691 /* FullscreenZoomInitialFrame.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDBFCC431A9FF44800A7B691 /* FullscreenZoomInitialFrame.mm */; };
@@ -783,6 +784,7 @@
C54237EE16B8955800E638FC /* PasteboardNotifications.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteboardNotifications.mm; sourceTree = "<group>"; };
C5E1AFFD16B22179006CC1F2 /* execCopy.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = execCopy.html; sourceTree = "<group>"; };
C95501BE19AD2FAF0049BE3E /* Preferences.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Preferences.mm; sourceTree = "<group>"; };
+ CD225C071C45A69200140761 /* ParsedContentRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParsedContentRange.cpp; sourceTree = "<group>"; };
CD5393C71757BA9700C07123 /* MD5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD5.cpp; sourceTree = "<group>"; };
CD5393C91757BAC400C07123 /* SHA1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SHA1.cpp; sourceTree = "<group>"; };
CD5451E919E41F9D0016936F /* CSSParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSParser.cpp; sourceTree = "<group>"; };
@@ -989,6 +991,7 @@
26F6E1EF1ADC749B00DE696B /* DFAMinimizer.cpp */,
41973B5A1AF2286A006C7B36 /* FileSystem.cpp */,
14464012167A8305000BD218 /* LayoutUnit.cpp */,
+ CD225C071C45A69200140761 /* ParsedContentRange.cpp */,
41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */,
CDC2C7141797089D00E627FB /* TimeRanges.cpp */,
440A1D3814A0103A008A66F2 /* URL.cpp */,
@@ -1835,6 +1838,7 @@
1CB9BC381A67482300FE5678 /* WeakPtr.cpp in Sources */,
2E7765CD16C4D80A00BA2BB1 /* mainIOS.mm in Sources */,
2D8104CC1BEC13E70020DA46 /* FindInPage.mm in Sources */,
+ CD225C081C45A69200140761 /* ParsedContentRange.cpp in Sources */,
41973B5D1AF22875006C7B36 /* SharedBuffer.cpp in Sources */,
2DD355361BD08378005DF4A7 /* AutoLayoutIntegration.mm in Sources */,
7AA6A1521AAC0B31002B2ED3 /* WorkQueue.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp (0 => 195764)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp 2016-01-28 19:17:17 UTC (rev 195764)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 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"
+
+#include <WebCore/ParsedContentRange.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(WebCore, ParsedContentRangeFromString)
+{
+ // Basic parsing
+ ASSERT_TRUE(ParsedContentRange("bytes 0-1/2").isValid());
+ ASSERT_TRUE(ParsedContentRange("bytes 0-1/*").isValid());
+ ASSERT_EQ(0, ParsedContentRange("bytes 0-1/2").firstBytePosition());
+ ASSERT_EQ(1, ParsedContentRange("bytes 0-1/2").lastBytePosition());
+ ASSERT_EQ(2, ParsedContentRange("bytes 0-1/2").instanceLength());
+ ASSERT_EQ(ParsedContentRange::UnknownLength, ParsedContentRange("bytes 0-1/*").instanceLength());
+
+ // Whitespace errors
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0 -1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0- 1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1 /*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/ *").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/* ").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/ 2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/2 ").isValid());
+
+ // Non-digit errors
+ ASSERT_FALSE(ParsedContentRange("bytes abcd-1/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-abcd/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/abcd").isValid());
+
+ // Range requirement errors
+ ASSERT_FALSE(ParsedContentRange("bytes 1-0/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-2/1").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 2/0-1").isValid());
+ ASSERT_FALSE(ParsedContentRange("abcd 0/1-2").isValid());
+
+ // Negative value errors
+ ASSERT_FALSE(ParsedContentRange("bytes -0-1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes -1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0--0/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/-2").isValid());
+
+ // Edge cases
+ ASSERT_TRUE(ParsedContentRange("bytes 9223372036854775805-9223372036854775806/9223372036854775807").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 9223372036854775808-9223372036854775809/9223372036854775810").isValid());
+}
+
+TEST(WebCore, ParsedContentRangeFromValues)
+{
+ ASSERT_TRUE(ParsedContentRange(0, 1, 2).isValid());
+ ASSERT_TRUE(ParsedContentRange(0, 1, ParsedContentRange::UnknownLength).isValid());
+ ASSERT_FALSE(ParsedContentRange().isValid());
+ ASSERT_FALSE(ParsedContentRange(1, 0, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 2, 1).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 0, 0).isValid());
+ ASSERT_FALSE(ParsedContentRange(-1, 1, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, -1, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 1, -2).isValid());
+ ASSERT_FALSE(ParsedContentRange(-2, -1, 2).isValid());
+}
+
+TEST(WebCore, ParsedContentRangeToString)
+{
+ ASSERT_STREQ("bytes 0-1/2", ParsedContentRange(0, 1, 2).headerValue().utf8().data());
+ ASSERT_STREQ("bytes 0-1/*", ParsedContentRange(0, 1, ParsedContentRange::UnknownLength).headerValue().utf8().data());
+ ASSERT_STREQ("", ParsedContentRange().headerValue().utf8().data());
+}
+
+}