[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

jianli at chromium.org jianli at chromium.org
Wed Dec 22 12:26:28 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 4c6124fed6aab9f2421664f298f8e79672ab2e34
Author: jianli at chromium.org <jianli at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Aug 23 20:09:56 2010 +0000

    Handle blob resource.
    https://bugs.webkit.org/show_bug.cgi?id=43941
    
    Reviewed by Darin Fisher.
    
    JavaScriptCore:
    
    * JavaScriptCore.exp: Add an export that is neede by BlobResourceHandle.
    
    WebCore:
    
    To provide lower level blob reosurce handling for all possible ports,
    BlobResourceHandle derived from ResourceHandle is implemented. It provides
    both synchronous and asynchronous resource loading for blob URL.
    
    BlobResourceHandle needs to create a FileStreamProxy instance in order to
    asynchronous file stream operation. To achive this, a hook createAsyncFileStream
    is added to ResourceHandleClient interface. When ResourceLoader implements
    ths hook, it creates and returns FileStreamProxy.
    
    BlobResourceHandle.* is not added to chromium port since it will implement
    its own blob resource handling.
    
    * Android.mk:
    * CMakeLists.txt:
    * GNUmakefile.am:
    * WebCore.pro:
    * WebCore.vcproj/WebCore.vcproj:
    * WebCore.xcodeproj/project.pbxproj:
    * loader/ResourceLoader.cpp:
    (WebCore::ResourceLoader::createAsyncFileStream): Create and return FileStreamProxy.
    * loader/ResourceLoader.h:
    * page/SecurityOrigin.cpp: Add the support to get and validate the origin of blob URL.
    (WebCore::SecurityOrigin::create):
    (WebCore::SecurityOrigin::canLoad):
    * platform/network/BlobRegistryImpl.cpp:
    (WebCore::BlobRegistryImpl::appendStorageItems): Fix a bug that the length is not subtracted.
    * platform/network/BlobResourceHandle.cpp: Added.
    * platform/network/BlobResourceHandle.h: Added.
    * platform/network/HTTPParsers.cpp:
    (WebCore::parseRange):
    * platform/network/HTTPParsers.h:
    * platform/network/ResourceHandle.cpp: Hook up with asynchronous blob resource handling.
    (WebCore::ResourceHandle::create):
    * platform/network/ResourceHandle.h:
    * platform/network/ResourceHandleClient.h:
    (WebCore::ResourceHandleClient::createAsyncFileStream): Add a hook.
    * platform/network/mac/ResourceHandleMac.mm:
    (WebCore::ResourceHandle::loadResourceSynchronously): Hook up with synchronous blob resource handling.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65827 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 378f450..6ce7cb5 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,12 @@
+2010-08-23  Jian Li  <jianli at chromium.org>
+
+        Reviewed by Darin Fisher.
+
+        Handle blob resource.
+        https://bugs.webkit.org/show_bug.cgi?id=43941
+
+        * JavaScriptCore.exp: Add an export that is neede by BlobResourceHandle.
+
 2010-08-19  Andreas Kling  <andreas.kling at nokia.com>
 
         Reviewed by Geoffrey Garen.
diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp
index 5cfa1c2..4131e23 100644
--- a/JavaScriptCore/JavaScriptCore.exp
+++ b/JavaScriptCore/JavaScriptCore.exp
@@ -534,6 +534,7 @@ __ZNK3JSC9HashTable11deleteTableEv
 __ZNK3WTF12AtomicString5lowerEv
 __ZNK3WTF6String11toIntStrictEPbi
 __ZNK3WTF6String12toUIntStrictEPbi
+__ZNK3WTF6String13toInt64StrictEPbi
 __ZNK3WTF6String14threadsafeCopyEv
 __ZNK3WTF6String15stripWhiteSpaceEv
 __ZNK3WTF6String16removeCharactersEPFbtE
diff --git a/WebCore/Android.mk b/WebCore/Android.mk
index e8cd8b8..19dbed0 100644
--- a/WebCore/Android.mk
+++ b/WebCore/Android.mk
@@ -532,6 +532,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
 	platform/network/AuthenticationChallengeBase.cpp \
 	platform/network/BlobData.cpp \
 	platform/network/BlobRegistryImpl.cpp \
+	platform/network/BlobResourceHandle.cpp \
 	platform/network/Credential.cpp \
 	platform/network/CredentialStorage.cpp \
 	platform/network/FormData.cpp \
diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt
index 209f6b3..33baf13 100644
--- a/WebCore/CMakeLists.txt
+++ b/WebCore/CMakeLists.txt
@@ -1309,6 +1309,7 @@ SET(WebCore_SOURCES
     platform/network/AuthenticationChallengeBase.cpp
     platform/network/BlobData.cpp
     platform/network/BlobRegistryImpl.cpp
+    platform/network/BlobResourceHandle.cpp
     platform/network/Credential.cpp
     platform/network/FormData.cpp
     platform/network/FormDataBuilder.cpp
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 62d62a9..ffe744a 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -41,6 +41,52 @@
 
 2010-08-23  Jian Li  <jianli at chromium.org>
 
+        Reviewed by Darin Fisher.
+
+        Handle blob resource.
+        https://bugs.webkit.org/show_bug.cgi?id=43941
+
+        To provide lower level blob reosurce handling for all possible ports,
+        BlobResourceHandle derived from ResourceHandle is implemented. It provides
+        both synchronous and asynchronous resource loading for blob URL.
+
+        BlobResourceHandle needs to create a FileStreamProxy instance in order to
+        asynchronous file stream operation. To achive this, a hook createAsyncFileStream
+        is added to ResourceHandleClient interface. When ResourceLoader implements
+        ths hook, it creates and returns FileStreamProxy.
+
+        BlobResourceHandle.* is not added to chromium port since it will implement
+        its own blob resource handling.
+
+        * Android.mk:
+        * CMakeLists.txt:
+        * GNUmakefile.am:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::createAsyncFileStream): Create and return FileStreamProxy.
+        * loader/ResourceLoader.h:
+        * page/SecurityOrigin.cpp: Add the support to get and validate the origin of blob URL.
+        (WebCore::SecurityOrigin::create):
+        (WebCore::SecurityOrigin::canLoad):
+        * platform/network/BlobRegistryImpl.cpp:
+        (WebCore::BlobRegistryImpl::appendStorageItems): Fix a bug that the length is not subtracted.
+        * platform/network/BlobResourceHandle.cpp: Added.
+        * platform/network/BlobResourceHandle.h: Added.
+        * platform/network/HTTPParsers.cpp:
+        (WebCore::parseRange):
+        * platform/network/HTTPParsers.h:
+        * platform/network/ResourceHandle.cpp: Hook up with asynchronous blob resource handling.
+        (WebCore::ResourceHandle::create):
+        * platform/network/ResourceHandle.h:
+        * platform/network/ResourceHandleClient.h:
+        (WebCore::ResourceHandleClient::createAsyncFileStream): Add a hook.
+        * platform/network/mac/ResourceHandleMac.mm:
+        (WebCore::ResourceHandle::loadResourceSynchronously): Hook up with synchronous blob resource handling.
+
+2010-08-23  Jian Li  <jianli at chromium.org>
+
         Reviewed by David Levin.
 
         Remove unneeded BlobRegistryImpl.* and WebBlobRegistryImpl.* from
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index 9f53ec1..82fc19e 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -2103,6 +2103,8 @@ webcore_sources += \
 	WebCore/platform/network/BlobRegistry.h \
 	WebCore/platform/network/BlobRegistryImpl.cpp \
 	WebCore/platform/network/BlobRegistryImpl.h \
+	WebCore/platform/network/BlobResourceHandle.cpp \
+	WebCore/platform/network/BlobResourceHandle.h \
 	WebCore/platform/network/BlobStorageData.h \
 	WebCore/platform/network/Credential.cpp \
 	WebCore/platform/network/Credential.h \
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index 80348dc..3aa750f 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -941,6 +941,7 @@ SOURCES += \
     platform/network/AuthenticationChallengeBase.cpp \
     platform/network/BlobData.cpp \
     platform/network/BlobRegistryImpl.cpp \
+    platform/network/BlobResourceHandle.cpp \
     platform/network/Credential.cpp \
     platform/network/FormData.cpp \
     platform/network/FormDataBuilder.cpp \
@@ -1742,6 +1743,7 @@ HEADERS += \
     platform/network/BlobData.h \
     platform/network/BlobRegistry.h \
     platform/network/BlobRegistryImpl.h \
+    platform/network/BlobResourceHandle.h \
     platform/network/BlobStorageData.h \
     platform/network/Credential.h \
     platform/network/FormDataBuilder.h \
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index 3ea4b5f..5ae3927 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -26872,6 +26872,14 @@
 					>
 				</File>
 				<File
+					RelativePath="..\platform\network\BlobResourceHandle.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\platform\network\BlobResourceHandle.h"
+					>
+				</File>
+				<File
 					RelativePath="..\platform\network\BlobStorageData.h"
 					>
 				</File>
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index 5df4943..e2532a9 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -704,6 +704,8 @@
 		2EA768040FE7126400AB9C8A /* WorkerScriptLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EA768030FE7126400AB9C8A /* WorkerScriptLoaderClient.h */; };
 		2EAFAF0E10E2AF2D007ED3D6 /* Blob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2EAFAF0B10E2AF2D007ED3D6 /* Blob.cpp */; };
 		2EAFAF0F10E2AF2D007ED3D6 /* Blob.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EAFAF0C10E2AF2D007ED3D6 /* Blob.h */; };
+		2EB4BCD2121F03E300EC4885 /* BlobResourceHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2EB4BCD0121F03E300EC4885 /* BlobResourceHandle.cpp */; };
+		2EB4BCD3121F03E300EC4885 /* BlobResourceHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */; };
 		2ECF7ADC10162B3800427DE7 /* JSErrorEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ECF7ADA10162B3800427DE7 /* JSErrorEvent.cpp */; };
 		2ECF7ADD10162B3800427DE7 /* JSErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECF7ADB10162B3800427DE7 /* JSErrorEvent.h */; };
 		2ECF7AE110162B5800427DE7 /* ErrorEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */; };
@@ -6525,6 +6527,8 @@
 		2EAFAF0B10E2AF2D007ED3D6 /* Blob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Blob.cpp; sourceTree = "<group>"; };
 		2EAFAF0C10E2AF2D007ED3D6 /* Blob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Blob.h; sourceTree = "<group>"; };
 		2EAFAF0D10E2AF2D007ED3D6 /* Blob.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Blob.idl; sourceTree = "<group>"; };
+		2EB4BCD0121F03E300EC4885 /* BlobResourceHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlobResourceHandle.cpp; sourceTree = "<group>"; };
+		2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobResourceHandle.h; sourceTree = "<group>"; };
 		2ECF7ADA10162B3800427DE7 /* JSErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSErrorEvent.cpp; sourceTree = "<group>"; };
 		2ECF7ADB10162B3800427DE7 /* JSErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSErrorEvent.h; sourceTree = "<group>"; };
 		2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorEvent.cpp; sourceTree = "<group>"; };
@@ -12468,6 +12472,8 @@
 				2EDEF1EF121B0EFC00726DB2 /* BlobRegistry.h */,
 				2EDEF1F0121B0EFC00726DB2 /* BlobRegistryImpl.cpp */,
 				2EDEF1F1121B0EFC00726DB2 /* BlobRegistryImpl.h */,
+				2EB4BCD0121F03E300EC4885 /* BlobResourceHandle.cpp */,
+				2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */,
 				2EDEF1F2121B0EFC00726DB2 /* BlobStorageData.h */,
 				514C76580CE923A1007EF3CD /* Credential.cpp */,
 				514C76590CE923A1007EF3CD /* Credential.h */,
@@ -20354,6 +20360,7 @@
 				89C0DD7B121F0C69009E17CA /* FileSystemCallbacks.h in Headers */,
 				CE057FA61220731100A476D5 /* DocumentMarkerController.h in Headers */,
 				9F0D6B2F121BFEBA006C0288 /* InspectorProfilerAgent.h in Headers */,
+				2EB4BCD3121F03E300EC4885 /* BlobResourceHandle.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -22808,6 +22815,7 @@
 				89C0DD7A121F0C69009E17CA /* FileSystemCallbacks.cpp in Sources */,
 				CE057FA51220731100A476D5 /* DocumentMarkerController.cpp in Sources */,
 				9F0D6B2E121BFEBA006C0288 /* InspectorProfilerAgent.cpp in Sources */,
+				2EB4BCD2121F03E300EC4885 /* BlobResourceHandle.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp
index 57e53eb..c7308b9 100644
--- a/WebCore/loader/ResourceLoader.cpp
+++ b/WebCore/loader/ResourceLoader.cpp
@@ -32,6 +32,7 @@
 
 #include "ApplicationCacheHost.h"
 #include "DocumentLoader.h"
+#include "FileStreamProxy.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "InspectorTimelineAgent.h"
@@ -511,4 +512,12 @@ void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& poli
         policy = StorageAllowedInMemoryOnly;    
 }
 
+#if ENABLE(BLOB)
+AsyncFileStream* ResourceLoader::createAsyncFileStream(FileStreamClient* client)
+{
+    // It is OK to simply return a pointer since FileStreamProxy::create adds an extra ref.
+    return FileStreamProxy::create(m_frame->document()->scriptExecutionContext(), client).get();
+}
+#endif
+
 }
diff --git a/WebCore/loader/ResourceLoader.h b/WebCore/loader/ResourceLoader.h
index cbdd8c2..9513fdb 100644
--- a/WebCore/loader/ResourceLoader.h
+++ b/WebCore/loader/ResourceLoader.h
@@ -118,6 +118,9 @@ namespace WebCore {
 #if USE(CFNETWORK)
         virtual bool shouldCacheResponse(ResourceHandle*, CFCachedURLResponseRef);
 #endif
+#if ENABLE(BLOB)
+        virtual AsyncFileStream* createAsyncFileStream(FileStreamClient*);
+#endif
 
         ResourceHandle* handle() const { return m_handle.get(); }
         bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; }
diff --git a/WebCore/page/SecurityOrigin.cpp b/WebCore/page/SecurityOrigin.cpp
index f759402..5b51501 100644
--- a/WebCore/page/SecurityOrigin.cpp
+++ b/WebCore/page/SecurityOrigin.cpp
@@ -29,6 +29,7 @@
 #include "config.h"
 #include "SecurityOrigin.h"
 
+#include "BlobURL.h"
 #include "Document.h"
 #include "FileSystem.h"
 #include "KURL.h"
@@ -123,6 +124,10 @@ PassRefPtr<SecurityOrigin> SecurityOrigin::create(const KURL& url, SandboxFlags
 {
     if (!url.isValid())
         return adoptRef(new SecurityOrigin(KURL(), sandboxFlags));
+#if ENABLE(BLOB)
+    if (url.protocolIs("blob"))
+        return adoptRef(new SecurityOrigin(BlobURL::getOrigin(url), sandboxFlags));
+#endif
     return adoptRef(new SecurityOrigin(url, sandboxFlags));
 }
 
@@ -275,6 +280,14 @@ bool SecurityOrigin::isAccessWhiteListed(const SecurityOrigin* targetOrigin) con
   
 bool SecurityOrigin::canLoad(const KURL& url, const String& referrer, Document* document)
 {
+#if ENABLE(BLOB)
+    if (url.protocolIs("blob") && document) {
+        SecurityOrigin* documentOrigin = document->securityOrigin();
+        RefPtr<SecurityOrigin> targetOrigin = SecurityOrigin::create(url);
+        return documentOrigin->isSameSchemeHostPort(targetOrigin.get());
+    }
+#endif
+
     if (!SchemeRegistry::shouldTreatURLAsLocal(url.string()))
         return true;
 
diff --git a/WebCore/platform/network/BlobRegistryImpl.cpp b/WebCore/platform/network/BlobRegistryImpl.cpp
index 00c0b75..ee872e6 100644
--- a/WebCore/platform/network/BlobRegistryImpl.cpp
+++ b/WebCore/platform/network/BlobRegistryImpl.cpp
@@ -113,6 +113,7 @@ void BlobRegistryImpl::appendStorageItems(BlobStorageData* blobStorageData, cons
             ASSERT(iter->type == BlobDataItem::File);
             blobStorageData->m_data.appendFile(iter->path, iter->offset + offset, newLength, iter->expectedModificationTime);
         }
+        length -= newLength;
         offset = 0;
     }
 }
diff --git a/WebCore/platform/network/BlobResourceHandle.cpp b/WebCore/platform/network/BlobResourceHandle.cpp
new file mode 100644
index 0000000..63335f6
--- /dev/null
+++ b/WebCore/platform/network/BlobResourceHandle.cpp
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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"
+
+#if ENABLE(BLOB)
+
+#include "BlobResourceHandle.h"
+
+#include "AsyncFileStream.h"
+#include "BlobRegistryImpl.h"
+#include "FileStream.h"
+#include "FileSystem.h"
+#include "HTTPParsers.h"
+#include "KURL.h"
+#include "ResourceError.h"
+#include "ResourceLoader.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+
+namespace WebCore {
+
+static const unsigned bufferSize = 1024;
+static const int maxVectorLength = 0x7fffffff;
+static const long long positionNotSpecified = -1;
+
+static const int httpOK = 200;
+static const int httpPartialContent = 206;
+static const int httpNotAllowed = 403;
+static const int httpNotFound = 404;
+static const int httpRequestedRangeNotSatisfiable = 416;
+static const int httpInternalError = 500;
+static const char* httpOKText = "OK";
+static const char* httpPartialContentText = "Partial Content";
+static const char* httpNotAllowedText = "Not Allowed";
+static const char* httpNotFoundText = "Not Found";
+static const char* httpRequestedRangeNotSatisfiableText = "Requested Range Not Satisfiable";
+static const char* httpInternalErrorText = "Internal Server Error";
+
+static const int notFoundError = 1;
+static const int securityError = 2;
+static const int rangeError = 3;
+static const int notReadableError = 4;
+
+///////////////////////////////////////////////////////////////////////////////
+// BlobResourceSynchronousLoader
+
+namespace {
+
+class BlobResourceSynchronousLoader : public ResourceHandleClient {
+public:
+    BlobResourceSynchronousLoader(ResourceError&, ResourceResponse&, Vector<char>&);
+
+    virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
+    virtual void didReceiveData(ResourceHandle*, const char*, int, int /*lengthReceived*/);
+    virtual void didFinishLoading(ResourceHandle*);
+    virtual void didFail(ResourceHandle*, const ResourceError&);
+
+private:
+    ResourceError& m_error;
+    ResourceResponse& m_response;
+    Vector<char>& m_data;
+};
+
+BlobResourceSynchronousLoader::BlobResourceSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data)
+    : m_error(error)
+    , m_response(response)
+    , m_data(data)
+{
+}
+
+void BlobResourceSynchronousLoader::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response)
+{
+    // We cannot handle the size that is more than maximum integer.
+    const int intMaxForLength = 0x7fffffff;
+    if (response.expectedContentLength() > intMaxForLength) {
+        m_error = ResourceError(String(), notReadableError, response.url(), String());
+        return;
+    }
+
+    m_response = response;
+
+    // Read all the data.
+    m_data.resize(static_cast<size_t>(response.expectedContentLength()));
+    static_cast<BlobResourceHandle*>(handle)->readSync(m_data.data(), static_cast<int>(m_data.size()));
+}
+
+void BlobResourceSynchronousLoader::didReceiveData(ResourceHandle*, const char*, int, int)
+{
+}
+
+void BlobResourceSynchronousLoader::didFinishLoading(ResourceHandle*)
+{
+}
+
+void BlobResourceSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error)
+{
+    m_error = error;
+}
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BlobResourceHandle
+
+// static
+void BlobResourceHandle::loadResourceSynchronously(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
+{
+    BlobResourceSynchronousLoader loader(error, response, data);
+    RefPtr<BlobResourceHandle> handle = BlobResourceHandle::create(blobData, request, &loader, false);
+    handle->start();
+}
+
+static void delayedStart(void* context)
+{
+    static_cast<BlobResourceHandle*>(context)->start();
+}
+
+BlobResourceHandle::BlobResourceHandle(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceHandleClient* client, bool async)
+    : ResourceHandle(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 = adoptRef(client->createAsyncFileStream(this));
+        callOnMainThread(delayedStart, this);
+    } else
+        m_stream = FileStream::create();
+}
+
+BlobResourceHandle::~BlobResourceHandle()
+{
+    if (m_async) {
+        if (m_asyncStream)
+            m_asyncStream->stop();
+    } else {
+        if (m_stream)
+            m_stream->stop();
+    }
+}
+
+void BlobResourceHandle::cancel()
+{
+    if (m_async) {
+        if (m_asyncStream) {
+            m_asyncStream->stop();
+            m_asyncStream = 0;
+        }
+    }
+
+    m_aborted = true;
+}
+
+void BlobResourceHandle::start()
+{
+    // Do not continue if the request is aborted or an error occurs.
+    if (m_aborted || m_errorCode)
+        return;
+
+    // If the blob data is not found, fail now.
+    if (!m_blobData) {
+        m_errorCode = notFoundError;
+        notifyResponse();
+        return;
+    }
+
+    // Parse the "Range" header we care about.
+    String range = firstRequest().httpHeaderField("Range");
+    if (!range.isEmpty() && !parseRange(range, m_rangeOffset, m_rangeEnd, m_rangeSuffixLength)) {
+        m_errorCode = rangeError;
+        notifyResponse();
+        return;
+    }
+
+    if (m_async)
+        getSizeForNext();
+    else {
+        for (size_t i = 0; i < m_blobData->items().size() && !m_aborted && !m_errorCode; ++i)
+            getSizeForNext();
+        notifyResponse();
+    }
+}
+
+void BlobResourceHandle::getSizeForNext()
+{
+    // Do we finish validating and counting size for all items?
+    if (m_sizeItemCount >= m_blobData->items().size()) {
+        seek();
+
+        // Start reading if in asynchronous mode.
+        if (m_async) {
+            notifyResponse();
+            m_buffer.resize(bufferSize);
+            readAsync();
+        }
+        return;
+    }
+
+    const BlobDataItem& item = m_blobData->items().at(m_sizeItemCount);
+    switch (item.type) {
+    case BlobDataItem::Data:
+        didGetSize(item.length);
+        break;
+    case BlobDataItem::File:
+        if (m_async)
+            m_asyncStream->getSize(item.path, item.expectedModificationTime);
+        else
+            didGetSize(m_stream->getSize(item.path, item.expectedModificationTime));
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+}
+
+void BlobResourceHandle::didGetSize(long long size)
+{
+    // Do not continue if the request is aborted or an error occurs.
+    if (m_aborted || m_errorCode)
+        return;
+
+    // If the size is -1, it means the file has been moved or changed. Fail now.
+    if (size == -1) {
+        m_errorCode = notFoundError;
+        notifyResponse();
+        return;
+    }
+
+    // The size passed back is the size of the whole file. If the underlying item is a sliced file, we need to use the slice length.
+    const BlobDataItem& item = m_blobData->items().at(m_sizeItemCount);
+    if (item.type == BlobDataItem::File && item.length != BlobDataItem::toEndOfFile)
+        size = item.length;
+
+    // Cache the size.
+    m_itemLengthList.append(size);
+
+    // Count the size.
+    m_totalRemainingSize += size;
+    m_sizeItemCount++;
+
+    // Continue with the next item.
+    getSizeForNext();
+}
+
+void BlobResourceHandle::seek()
+{
+    // Convert from the suffix length to the range.
+    if (m_rangeSuffixLength != positionNotSpecified) {
+        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)
+        return;
+
+    // Skip the initial items that are not in the range.
+    long long offset = m_rangeOffset;
+    for (m_readItemCount = 0; m_readItemCount < m_blobData->items().size() && offset >= m_itemLengthList[m_readItemCount]; ++m_readItemCount)
+        offset -= m_itemLengthList[m_readItemCount];
+
+    // Set the offset that need to jump to for the first item in the range.
+    m_currentItemReadSize = offset;
+
+    // Adjust the total remaining size in order not to go beyond the range.
+    if (m_rangeEnd != positionNotSpecified) {
+        long long rangeSize = m_rangeEnd - m_rangeOffset + 1;
+        if (m_totalRemainingSize > rangeSize)
+            m_totalRemainingSize = rangeSize;
+    } else
+        m_totalRemainingSize -= m_rangeOffset;
+}
+
+int BlobResourceHandle::readSync(char* buf, int length)
+{
+    ASSERT(!m_async);
+
+    int offset = 0;
+    int remaining = length;
+    while (remaining) {
+        // Do not continue if the request is aborted or an error occurs.
+        if (m_aborted || m_errorCode)
+            break;
+
+        // If there is no more remaining data to read, we are done.
+        if (!m_totalRemainingSize || m_readItemCount >= m_blobData->items().size())
+            break;
+        
+        const BlobDataItem& item = m_blobData->items().at(m_readItemCount);
+        int bytesRead = 0;
+        if (item.type == BlobDataItem::Data)
+            bytesRead = readDataSync(item, buf + offset, remaining);
+        else if (item.type == BlobDataItem::File)
+            bytesRead = readFileSync(item, buf + offset, remaining);
+        else
+            ASSERT_NOT_REACHED();
+
+        if (bytesRead > 0) {
+            offset += bytesRead;
+            remaining -= bytesRead;
+        }
+    }
+
+    int result;
+    if (m_aborted || m_errorCode)
+        result = -1;
+    else
+        result = length - remaining;
+
+    notifyReceiveData(buf, result);
+    if (!result)
+        notifyFinish();
+
+    return result;
+}
+
+int BlobResourceHandle::readDataSync(const BlobDataItem& item, char* buf, int length)
+{
+    ASSERT(!m_async);
+
+    long long remaining = item.length - m_currentItemReadSize;
+    int bytesToRead = (length > remaining) ? static_cast<int>(remaining) : length;
+    if (bytesToRead > m_totalRemainingSize)
+        bytesToRead = static_cast<int>(m_totalRemainingSize);
+    memcpy(buf, item.data.data() + item.offset + m_currentItemReadSize, bytesToRead);
+    m_totalRemainingSize -= bytesToRead;
+
+    m_currentItemReadSize += bytesToRead;
+    if (m_currentItemReadSize == item.length) {
+        m_readItemCount++;
+        m_currentItemReadSize = 0;
+    }
+
+    return bytesToRead;
+}
+
+int BlobResourceHandle::readFileSync(const BlobDataItem& item, char* buf, int length)
+{
+    ASSERT(!m_async);
+
+    if (!m_fileOpened) {
+        long long bytesToRead = m_itemLengthList[m_readItemCount] - m_currentItemReadSize;
+        if (bytesToRead > m_totalRemainingSize)
+            bytesToRead = m_totalRemainingSize;
+        bool success = m_stream->openForRead(item.path, item.offset + m_currentItemReadSize, bytesToRead);
+        m_currentItemReadSize = 0;
+        if (!success) {
+            m_errorCode = notReadableError;
+            return 0;
+        }
+
+        m_fileOpened = true;
+    }
+
+    int bytesRead = m_stream->read(buf, length);
+    if (bytesRead < 0) {
+        m_errorCode = notReadableError;
+        return 0;
+    }
+    if (!bytesRead) {
+        m_stream->close();
+        m_fileOpened = false;
+        m_readItemCount++;
+    } else
+        m_totalRemainingSize -= bytesRead;
+
+    return bytesRead;
+}
+
+void BlobResourceHandle::readAsync()
+{
+    ASSERT(m_async);
+
+    // Do not continue if the request is aborted or an error occurs.
+    if (m_aborted || m_errorCode)
+        return;
+
+    // If there is no more remaining data to read, we are done.
+    if (!m_totalRemainingSize || m_readItemCount >= m_blobData->items().size()) {
+        notifyFinish();
+        return;
+    }
+
+    const BlobDataItem& item = m_blobData->items().at(m_readItemCount);
+    if (item.type == BlobDataItem::Data)
+        readDataAsync(item);
+    else if (item.type == BlobDataItem::File)
+        readFileAsync(item);
+    else
+        ASSERT_NOT_REACHED();
+}
+
+void BlobResourceHandle::readDataAsync(const BlobDataItem& item)
+{
+    ASSERT(m_async);
+
+    long long bytesToRead = item.length - m_currentItemReadSize;
+    if (bytesToRead > m_totalRemainingSize)
+        bytesToRead = m_totalRemainingSize;
+    consumeData(item.data.data() + item.offset + m_currentItemReadSize, static_cast<int>(bytesToRead));
+    m_currentItemReadSize = 0;
+}
+
+void BlobResourceHandle::readFileAsync(const BlobDataItem& item)
+{
+    ASSERT(m_async);
+
+    if (m_fileOpened) {
+        m_asyncStream->read(m_buffer.data(), m_buffer.size());
+        return;
+    }
+
+    long long bytesToRead = m_itemLengthList[m_readItemCount] - m_currentItemReadSize;
+    if (bytesToRead > m_totalRemainingSize)
+        bytesToRead = static_cast<int>(m_totalRemainingSize);
+    m_asyncStream->openForRead(item.path, item.offset + m_currentItemReadSize, bytesToRead);
+    m_fileOpened = true;
+    m_currentItemReadSize = 0;
+}
+
+void BlobResourceHandle::didOpen(bool success)
+{
+    ASSERT(m_async);
+
+    if (!success) {
+        failed(notReadableError);
+        return;
+    }
+
+    // Continue the reading.
+    readAsync();
+}
+
+void BlobResourceHandle::didRead(int bytesRead)
+{
+    consumeData(m_buffer.data(), bytesRead);
+}
+
+void BlobResourceHandle::consumeData(const char* data, int bytesRead)
+{
+    ASSERT(m_async);
+
+    m_totalRemainingSize -= bytesRead;
+
+    // Notify the client.
+    if (bytesRead)
+        notifyReceiveData(data, bytesRead);
+
+    if (m_fileOpened) {
+        // When the current item is a file item, the reading is completed only if bytesRead is 0.
+        if (!bytesRead) {
+            // Close the file.
+            m_fileOpened = false;
+            m_asyncStream->close();
+
+            // Move to the next item.
+            m_readItemCount++;
+        }
+    } else {
+        // Otherwise, we read the current text item as a whole and move to the next item.
+        m_readItemCount++;
+    }
+
+    // Continue the reading.
+    readAsync();
+}
+
+void BlobResourceHandle::failed(int errorCode)
+{
+    ASSERT(m_async);
+
+    // Notify the client.
+    notifyFail(errorCode);
+
+    // Close the file if needed.
+    if (m_fileOpened) {
+        m_fileOpened = false;
+        m_asyncStream->close();
+    }
+}
+
+void BlobResourceHandle::notifyResponse()
+{
+    if (!client())
+        return;
+
+    if (m_errorCode) {
+        notifyResponseOnError();
+        notifyFinish();
+    } else
+        notifyResponseOnSuccess();
+}
+
+void BlobResourceHandle::notifyResponseOnSuccess()
+{
+    bool isRangeRequest = m_rangeOffset != positionNotSpecified;
+    ResourceResponse response(firstRequest().url(), m_blobData->contentType(), m_totalRemainingSize, String(), String());
+    response.setExpectedContentLength(m_totalRemainingSize);
+    response.setHTTPStatusCode(isRangeRequest ? httpPartialContent : httpOK);
+    response.setHTTPStatusText(isRangeRequest ? httpPartialContentText : httpOKText);
+    if (!m_blobData->contentDisposition().isEmpty())
+        response.setHTTPHeaderField("Content-Disposition", m_blobData->contentDisposition());
+    client()->didReceiveResponse(this, response);
+}
+
+void BlobResourceHandle::notifyResponseOnError()
+{
+    ASSERT(m_errorCode);
+
+    ResourceResponse response(firstRequest().url(), String(), 0, String(), String());
+    switch (m_errorCode) {
+    case rangeError:
+        response.setHTTPStatusCode(httpRequestedRangeNotSatisfiable);
+        response.setHTTPStatusText(httpRequestedRangeNotSatisfiableText);
+        break;
+    case notFoundError:
+        response.setHTTPStatusCode(httpNotFound);
+        response.setHTTPStatusText(httpNotFoundText);
+        break;
+    case securityError:
+        response.setHTTPStatusCode(httpNotAllowed);
+        response.setHTTPStatusText(httpNotAllowedText);
+        break;
+    default:
+        response.setHTTPStatusCode(httpInternalError);
+        response.setHTTPStatusText(httpInternalErrorText);
+        break;
+    }
+    client()->didReceiveResponse(this, response);
+}
+
+void BlobResourceHandle::notifyReceiveData(const char* data, int bytesRead)
+{
+    if (client())
+        client()->didReceiveData(this, data, bytesRead, bytesRead);
+}
+
+void BlobResourceHandle::notifyFail(int errorCode)
+{
+    if (client())
+        client()->didFail(this, ResourceError(String(), errorCode, firstRequest().url(), String()));
+}
+
+void BlobResourceHandle::notifyFinish()
+{
+    if (client())
+        client()->didFinishLoading(this);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB)
+
diff --git a/WebCore/platform/network/BlobResourceHandle.h b/WebCore/platform/network/BlobResourceHandle.h
new file mode 100644
index 0000000..b2a0854
--- /dev/null
+++ b/WebCore/platform/network/BlobResourceHandle.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 BlobResourceHandle_h
+#define BlobResourceHandle_h
+
+#if ENABLE(BLOB)
+
+#include "FileStreamClient.h"
+#include "PlatformString.h"
+#include "ResourceHandle.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AsyncFileStream;
+class BlobDataItem;
+class BlobStorageData;
+class FileStream;
+class ResourceHandleClient;
+class ResourceRequest;
+
+class BlobResourceHandle : public FileStreamClient, public ResourceHandle  {
+public:
+    static PassRefPtr<BlobResourceHandle> create(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceHandleClient* client, bool async = true)
+    {
+        return adoptRef(new BlobResourceHandle(blobData, request, client, async));
+    }
+
+    static void loadResourceSynchronously(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data);
+
+    // FileStreamClient methods.
+    virtual void didGetSize(long long);
+    virtual void didOpen(bool);
+    virtual void didRead(int);
+
+    // ResourceHandle methods.
+    virtual void cancel();
+
+    void start();
+    int readSync(char*, int);
+
+private:
+    BlobResourceHandle(PassRefPtr<BlobStorageData>, const ResourceRequest&, ResourceHandleClient*, bool async);
+    virtual ~BlobResourceHandle();
+
+    void getSizeForNext();
+    void seek();
+    void consumeData(const char* data, int bytesRead);
+    void failed(int errorCode);
+
+    void readAsync();
+    void readDataAsync(const BlobDataItem&);
+    void readFileAsync(const BlobDataItem&);
+
+    int readDataSync(const BlobDataItem&, char*, int);
+    int readFileSync(const BlobDataItem&, char*, int);
+
+    void notifyResponse();
+    void notifyResponseOnSuccess();
+    void notifyResponseOnError();
+    void notifyReceiveData(const char*, int);
+    void notifyFail(int errorCode);
+    void notifyFinish();
+
+    RefPtr<BlobStorageData> m_blobData;
+    bool m_async;
+    RefPtr<AsyncFileStream> m_asyncStream; // For asynchronous loading.
+    RefPtr<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;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB)
+
+#endif // BlobResourceHandle_h
diff --git a/WebCore/platform/network/HTTPParsers.cpp b/WebCore/platform/network/HTTPParsers.cpp
index b3f3d45..a1ba9d3 100644
--- a/WebCore/platform/network/HTTPParsers.cpp
+++ b/WebCore/platform/network/HTTPParsers.cpp
@@ -315,4 +315,61 @@ String extractReasonPhraseFromHTTPStatusLine(const String& statusLine)
     return statusLine.substring(spacePos + 1);
 }
 
+bool parseRange(const String& range, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength)
+{
+    // The format of "Range" header is defined in RFC 2616 Section 14.35.1.
+    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
+    // We don't support multiple range requests.
+
+    rangeOffset = rangeEnd = rangeSuffixLength = -1;
+
+    // The "bytes" unit identifier should be present.
+    static const char bytesStart[] = "bytes="; 
+    if (!range.startsWith(bytesStart, false))
+        return false;
+    String byteRange = range.substring(sizeof(bytesStart) - 1);
+
+    // The '-' character needs to be present.
+    int index = byteRange.find('-');
+    if (index == -1)
+        return false;
+
+    // If the '-' character is at the beginning, the suffix length, which specifies the last N bytes, is provided.
+    // Example:
+    //     -500
+    if (!index) {
+        String suffixLengthString = byteRange.substring(index + 1).stripWhiteSpace();
+        bool ok;
+        long long value = suffixLengthString.toInt64Strict(&ok);
+        if (ok)
+            rangeSuffixLength = value;
+        return true;
+    }
+
+    // Otherwise, the first-byte-position and the last-byte-position are provied.
+    // Examples:
+    //     0-499
+    //     500-
+    String firstBytePosStr = byteRange.left(index).stripWhiteSpace();
+    bool ok;
+    long long firstBytePos = firstBytePosStr.toInt64Strict(&ok);
+    if (!ok)
+        return false;
+
+    String lastBytePosStr = byteRange.substring(index + 1).stripWhiteSpace();
+    long long lastBytePos = -1;
+    if (!lastBytePosStr.isEmpty()) {
+        lastBytePos = lastBytePosStr.toInt64Strict(&ok);
+        if (!ok)
+            return false;
+    }
+
+    if (firstBytePos < 0 || !(lastBytePos == -1 || lastBytePos >= firstBytePos))
+        return false;
+
+    rangeOffset = firstBytePos;
+    rangeEnd = lastBytePos;
+    return true;
+}
+
 }
diff --git a/WebCore/platform/network/HTTPParsers.h b/WebCore/platform/network/HTTPParsers.h
index 9d6971b..55b8c7b 100644
--- a/WebCore/platform/network/HTTPParsers.h
+++ b/WebCore/platform/network/HTTPParsers.h
@@ -59,6 +59,9 @@ void findCharsetInMediaType(const String& mediaType, unsigned int& charsetPos, u
 XSSProtectionDisposition parseXSSProtectionHeader(const String&);
 String extractReasonPhraseFromHTTPStatusLine(const String&);
 
+// -1 could be set to one of the return parameters to indicate the value is not specified.
+bool parseRange(const String&, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength);
+
 }
 
 #endif
diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp
index 0575523..2da1d77 100644
--- a/WebCore/platform/network/ResourceHandle.cpp
+++ b/WebCore/platform/network/ResourceHandle.cpp
@@ -27,6 +27,7 @@
 #include "ResourceHandle.h"
 #include "ResourceHandleInternal.h"
 
+#include "BlobRegistry.h"
 #include "DNS.h"
 #include "Logging.h"
 #include "ResourceHandleClient.h"
@@ -54,6 +55,14 @@ ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleCli
 PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, ResourceHandleClient* client,
     Frame* frame, bool defersLoading, bool shouldContentSniff)
 {
+#if ENABLE(BLOB)
+    if (request.url().protocolIs("blob")) {
+        PassRefPtr<ResourceHandle> handle = blobRegistry().createResourceHandle(request, client);
+        if (handle)
+            return handle;
+    }
+#endif
+
     RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff)));
 
     if (newHandle->d->m_scheduledFailureType != NoFailure)
diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h
index 2edd4c9..d52076c 100644
--- a/WebCore/platform/network/ResourceHandle.h
+++ b/WebCore/platform/network/ResourceHandle.h
@@ -98,9 +98,10 @@ class ResourceHandle : public RefCounted<ResourceHandle>
     , public AuthenticationClient
 #endif
     {
-private:
+protected:
     ResourceHandle(const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff);
 
+private:
     enum FailureType {
         NoFailure,
         BlockedFailure,
diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h
index 0098010..97c0f54 100644
--- a/WebCore/platform/network/ResourceHandleClient.h
+++ b/WebCore/platform/network/ResourceHandleClient.h
@@ -44,8 +44,10 @@ class NSCachedURLResponse;
 #endif
 
 namespace WebCore {
+    class AsyncFileStream;
     class AuthenticationChallenge;
     class Credential;
+    class FileStreamClient;
     class KURL;
     class ProtectionSpace;
     class ResourceHandle;
@@ -92,6 +94,9 @@ namespace WebCore {
 #if USE(CFNETWORK)
         virtual bool shouldCacheResponse(ResourceHandle*, CFCachedURLResponseRef response) { return true; }
 #endif
+#if ENABLE(BLOB)
+        virtual AsyncFileStream* createAsyncFileStream(FileStreamClient*) { return 0; }
+#endif
     };
 
 }
diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm
index f7161ec..d014bb3 100644
--- a/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -29,6 +29,7 @@
 #import "AuthenticationChallenge.h"
 #import "AuthenticationMac.h"
 #import "Base64.h"
+#import "BlobRegistry.h"
 #import "BlockExceptions.h"
 #import "CredentialStorage.h"
 #import "DocLoader.h"
@@ -464,6 +465,12 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, S
 {
     LOG(Network, "ResourceHandle::loadResourceSynchronously:%@ allowStoredCredentials:%u", request.nsURLRequest(), storedCredentials);
 
+#if ENABLE(BLOB)
+    if (request.url().protocolIs("blob"))
+        if (blobRegistry().loadResourceSynchronously(request, error, response, data))
+            return;
+#endif
+
     NSError *nsError = nil;
     NSURLResponse *nsURLResponse = nil;
     NSData *result = nil;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list