[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 15:16:41 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit a8c47de0671244ef8e129f6b19d9cae7f69794d6
Author: jianli at chromium.org <jianli at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Oct 29 18:23:28 2010 +0000

    Support readAsArrayBuffer in FileReader and FileReaderSync
    https://bugs.webkit.org/show_bug.cgi?id=47691
    
    Reviewed by David Levin.
    
    WebCore:
    
    Merge the similar code in FileReader and FileReaderSync into
    FileReaderLoader.
    
    Test cases have been added to read-file-test-cases.js.
    
    * Android.jscbindings.mk:
    * CMakeLists.txt:
    * GNUmakefile.am:
    * WebCore.gypi:
    * WebCore.pro:
    * WebCore.vcproj/WebCore.vcproj:
    * WebCore.xcodeproj/project.pbxproj:
    * bindings/v8/custom/V8FileReaderCustom.cpp: Added.
    * fileapi/FileReader.cpp:
    (WebCore::FileReader::FileReader):
    (WebCore::FileReader::readAsArrayBuffer):
    (WebCore::FileReader::readAsBinaryString):
    (WebCore::FileReader::readAsText):
    (WebCore::FileReader::readAsDataURL):
    (WebCore::FileReader::readInternal):
    (WebCore::FileReader::doAbort):
    (WebCore::FileReader::terminate):
    (WebCore::FileReader::start):
    (WebCore::FileReader::didStartLoading):
    (WebCore::FileReader::didReceiveData):
    (WebCore::FileReader::didFinishLoading):
    (WebCore::FileReader::didFail):
    (WebCore::FileReader::fireEvent):
    (WebCore::FileReader::arrayBufferResult):
    (WebCore::FileReader::stringResult):
    * fileapi/FileReader.h:
    (WebCore::FileReader::readType):
    * fileapi/FileReader.idl:
    * fileapi/FileReaderLoader.cpp: Added.
    * fileapi/FileReaderLoader.h: Added.
    * fileapi/FileReaderLoaderClient.h: Added.
    * fileapi/FileReaderSync.cpp:
    (WebCore::FileReaderSync::FileReaderSync):
    (WebCore::FileReaderSync::readAsArrayBuffer):
    (WebCore::FileReaderSync::readAsBinaryString):
    (WebCore::FileReaderSync::readAsText):
    (WebCore::FileReaderSync::readAsDataURL):
    (WebCore::FileReaderSync::startLoading):
    * fileapi/FileReaderSync.h:
    * fileapi/FileReaderSync.idl:
    * html/canvas/ArrayBuffer.cpp:
    (WebCore::ArrayBuffer::create):
    * html/canvas/ArrayBuffer.h:
    * loader/ThreadableLoaderClient.h:
    
    LayoutTests:
    
    * fast/files/read-file-async-expected.txt:
    * fast/files/resources/read-common.js:
    (readBlobAsArrayBuffer):
    (_readBlobAsArrayBufferAsync):
    (_readBlobAsArrayBufferSync):
    (_readBlobAsBinaryStringSync):
    (_readBlobAsTextSync):
    (_readBlobAsDataURLSync):
    (logResult):
    (loaded):
    (_toString):
    (_isASCIIString):
    (_toHexadecimal):
    (_getElementAt):
    * fast/files/resources/read-file-test-cases.js:
    (testReadingNonExistentFileAsArrayBuffer):
    (testReadingEmptyFileAsArrayBuffer):
    (testReadingUTF8EncodedFileAsArrayBuffer):
    (testReadingBinaryFileAsArrayBuffer):
    (testMultipleReads):
    * fast/files/workers/resources/worker-read-file-sync.js:
    (testMultipleReadsSync):
    * fast/files/workers/worker-read-blob-sync-expected.txt:
    * fast/files/workers/worker-read-file-async-expected.txt:
    * fast/files/workers/worker-read-file-sync-expected.txt:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@70904 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 7bc86ad..92970e8 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,36 @@
+2010-10-29  Jian Li  <jianli at chromium.org>
+
+        Reviewed by David Levin.
+
+        Support readAsArrayBuffer in FileReader and FileReaderSync
+        https://bugs.webkit.org/show_bug.cgi?id=47691
+
+        * fast/files/read-file-async-expected.txt:
+        * fast/files/resources/read-common.js:
+        (readBlobAsArrayBuffer):
+        (_readBlobAsArrayBufferAsync):
+        (_readBlobAsArrayBufferSync):
+        (_readBlobAsBinaryStringSync):
+        (_readBlobAsTextSync):
+        (_readBlobAsDataURLSync):
+        (logResult):
+        (loaded):
+        (_toString):
+        (_isASCIIString):
+        (_toHexadecimal):
+        (_getElementAt):
+        * fast/files/resources/read-file-test-cases.js:
+        (testReadingNonExistentFileAsArrayBuffer):
+        (testReadingEmptyFileAsArrayBuffer):
+        (testReadingUTF8EncodedFileAsArrayBuffer):
+        (testReadingBinaryFileAsArrayBuffer):
+        (testMultipleReads):
+        * fast/files/workers/resources/worker-read-file-sync.js:
+        (testMultipleReadsSync):
+        * fast/files/workers/worker-read-blob-sync-expected.txt:
+        * fast/files/workers/worker-read-file-async-expected.txt:
+        * fast/files/workers/worker-read-file-sync-expected.txt:
+
 2010-10-29  Zhenyao Mo  <zmo at google.com>
 
         Unreviewed, webgl test expectations update.
diff --git a/LayoutTests/fast/files/read-file-async-expected.txt b/LayoutTests/fast/files/read-file-async-expected.txt
index d94eabb..28466d5 100644
--- a/LayoutTests/fast/files/read-file-async-expected.txt
+++ b/LayoutTests/fast/files/read-file-async-expected.txt
@@ -1,4 +1,10 @@
 
+Test reading a non-existent file as array buffer
+readyState: 0
+Received error event
+readyState: 2
+error code: 1
+Received loadend event
 Test reading a non-existent file as binary string
 readyState: 0
 Received error event
@@ -17,6 +23,15 @@ Received error event
 readyState: 2
 error code: 1
 Received loadend event
+Test reading an empty file as array buffer
+readyState: 0
+Received loadstart event
+readyState: 1
+Received load event
+readyState: 2
+result size: 0
+result: 
+Received loadend event
 Test reading an empty file as binary string
 readyState: 0
 Received loadstart event
@@ -44,6 +59,15 @@ readyState: 2
 result size: 5
 result: data:
 Received loadend event
+Test reading a UTF-8 file as array buffer
+readyState: 0
+Received loadstart event
+readyState: 1
+Received load event
+readyState: 2
+result size: 5
+result: Hello
+Received loadend event
 Test reading a UTF-8 file as binary string
 readyState: 0
 Received loadstart event
@@ -53,6 +77,15 @@ readyState: 2
 result size: 5
 result: Hello
 Received loadend event
+Test reading a binary file as array buffer
+readyState: 0
+Received loadstart event
+readyState: 1
+Received load event
+readyState: 2
+result size: 9
+result: 0x0 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
+Received loadend event
 Test reading a binary file as binary string
 readyState: 0
 Received loadstart event
diff --git a/LayoutTests/fast/files/resources/read-common.js b/LayoutTests/fast/files/resources/read-common.js
index abe324f..3b7447a 100644
--- a/LayoutTests/fast/files/resources/read-common.js
+++ b/LayoutTests/fast/files/resources/read-common.js
@@ -11,6 +11,14 @@ function buildBlob(items, contentType, builder)
 }
 
 // Reads a blob either asynchronously or synchronously.
+function readBlobAsArrayBuffer(testFiles, blob)
+{
+    if (isReadAsAsync())
+        _readBlobAsArrayBufferAsync(testFiles, blob);
+    else
+        _readBlobAsArrayBufferSync(testFiles, blob);
+}
+
 function readBlobAsBinaryString(testFiles, blob)
 {
     if (isReadAsAsync())
@@ -36,6 +44,12 @@ function readBlobAsDataURL(testFiles, blob)
 }
 
 // Reads a blob asynchronously.
+function _readBlobAsArrayBufferAsync(testFiles, blob)
+{
+    var reader = createReaderAsync(testFiles);
+    reader.readAsArrayBuffer(blob)
+}
+
 function _readBlobAsBinaryStringAsync(testFiles, blob)
 {
     var reader = createReaderAsync(testFiles);
@@ -55,12 +69,25 @@ function _readBlobAsDataURLAsync(testFiles, blob)
 }
 
 // Reads a blob synchronously.
+function _readBlobAsArrayBufferSync(testFiles, blob)
+{
+    var reader = createReaderSync();
+    try {
+        var result = reader.readAsArrayBuffer(blob);
+        logResult(result);
+    } catch (error) {
+        log("Received exception " + error.code + ": " + error.name);
+    }
+
+    runNextTest(testFiles);
+}
+
 function _readBlobAsBinaryStringSync(testFiles, blob)
 {
     var reader = createReaderSync();
     try {
         var result = reader.readAsBinaryString(blob);
-        log(result);
+        logResult(result);
     } catch (error) {
         log("Received exception " + error.code + ": " + error.name);
     }
@@ -73,7 +100,7 @@ function _readBlobAsTextSync(testFiles, blob, encoding)
     var reader = createReaderSync();
     try {
         var result = reader.readAsText(blob, encoding);
-        log(result);
+        logResult(result);
     } catch (error) {
         log("Received exception " + error.code + ": " + error.name);
     }
@@ -86,7 +113,7 @@ function _readBlobAsDataURLSync(testFiles, blob)
     var reader = createReaderSync();
     try {
         var result = reader.readAsDataURL(blob);
-        log(result);
+        logResult(result);
     } catch (error) {
         log("Received exception " + error.code + ": " + error.name);
     }
@@ -115,6 +142,19 @@ function createReaderSync()
     return new FileReaderSync();
 }
 
+// 'result' can be either an ArrayBuffer object or a string.
+function logResult(result)
+{
+    if (typeof result == 'object') {
+        log("result size: " + result.byteLength);
+        result = new Uint8Array(result, 0, result.byteLength);
+    } else
+        log("result size: " + result.length);
+
+    var resultOutput = _isASCIIString(result) ? _toString(result) : _toHexadecimal(result);
+    log("result: " + resultOutput);
+}
+
 function logEvent(event)
 {
     log("Received " + event.type + " event");
@@ -130,11 +170,9 @@ function loaded(event)
 {
     logEvent(event);
     log("readyState: " + event.target.readyState);
-    log("result size: " + event.target.result.length);
 
     var result = event.target.result;
-    var resultOutput = _isASCIIString(result) ? result : _toHexadecimal(result);
-    log("result: " + resultOutput);
+    logResult(result);
 }
 
 function loadFailed(event)
@@ -151,23 +189,42 @@ function loadEnded(testFiles, event)
 }
 
 // Helper functions.
-function _isASCIIString(str)
+
+// 'value' can be either an ArrayBufferView object or a string.
+function _toString(value)
 {
-    for (var i = 0; i < str.length; ++i) {
-        if (str.charCodeAt(i) >= 128)
+    if (typeof value == 'string')
+        return value;
+    var result = "";
+    for (var i = 0; i < value.length; ++i)
+        result += String.fromCharCode(value[i]);
+    return result;
+}
+
+// 'value' can be either an ArrayBufferView object or a string.
+function _isASCIIString(value)
+{
+    for (var i = 0; i < value.length; ++i) {
+        if (_getElementAt(value, i) >= 128)
             return false;
     }
     return true;
 }
 
-function _toHexadecimal(str)
+// 'value' can be either an ArrayBufferView object or a string.
+function _toHexadecimal(value)
 {
     var result = "";
-    for (var i = 0; i < str.length; ++i) {
-        var hex = "0x" + (str.charCodeAt(i) & 0xFF).toString(16);
+    for (var i = 0; i < value.length; ++i) {
+        var hex = "0x" + (_getElementAt(value, i) & 0xFF).toString(16);
         if (i > 0)
             result += " ";
         result += hex;
     }
     return result;
 }
+
+function _getElementAt(value, i)
+{
+    return (typeof value == 'string') ? value.charCodeAt(i) : value[i];
+}
diff --git a/LayoutTests/fast/files/resources/read-file-test-cases.js b/LayoutTests/fast/files/resources/read-file-test-cases.js
index e8b2c9c..38ee120 100644
--- a/LayoutTests/fast/files/resources/read-file-test-cases.js
+++ b/LayoutTests/fast/files/resources/read-file-test-cases.js
@@ -1,11 +1,15 @@
 var testCases = [
+    "testReadingNonExistentFileAsArrayBuffer",
     "testReadingNonExistentFileAsBinaryString",
     "testReadingNonExistentFileAsText",
     "testReadingNonExistentFileAsDataURL",
+    "testReadingEmptyFileAsArrayBuffer",
     "testReadingEmptyFileAsBinaryString",
     "testReadingEmptyFileAsText",
     "testReadingEmptyFileAsDataURL",
+    "testReadingUTF8EncodedFileAsArrayBuffer",
     "testReadingUTF8EncodedFileAsBinaryString",
+    "testReadingBinaryFileAsArrayBuffer",
     "testReadingBinaryFileAsBinaryString",
     "testReadingUTF8EncodedFileAsText",
     "testReadingUTF16BEBOMEncodedFileAsText",
@@ -29,6 +33,12 @@ function runNextTest(testFiles)
     }
 }
 
+function testReadingNonExistentFileAsArrayBuffer(testFiles)
+{
+    log("Test reading a non-existent file as array buffer");
+    readBlobAsArrayBuffer(testFiles, testFiles['non-existent']);
+}
+
 function testReadingNonExistentFileAsBinaryString(testFiles)
 {
     log("Test reading a non-existent file as binary string");
@@ -47,6 +57,12 @@ function testReadingNonExistentFileAsDataURL(testFiles)
     readBlobAsDataURL(testFiles, testFiles['non-existent']);
 }
 
+function testReadingEmptyFileAsArrayBuffer(testFiles)
+{
+    log("Test reading an empty file as array buffer");
+    readBlobAsArrayBuffer(testFiles, testFiles['empty-file']);
+}
+
 function testReadingEmptyFileAsBinaryString(testFiles)
 {
     log("Test reading an empty file as binary string");
@@ -65,12 +81,24 @@ function testReadingEmptyFileAsDataURL(testFiles)
     readBlobAsDataURL(testFiles, testFiles['empty-file']);
 }
 
+function testReadingUTF8EncodedFileAsArrayBuffer(testFiles)
+{
+    log("Test reading a UTF-8 file as array buffer");
+    readBlobAsArrayBuffer(testFiles, testFiles['UTF8-file']);
+}
+
 function testReadingUTF8EncodedFileAsBinaryString(testFiles)
 {
     log("Test reading a UTF-8 file as binary string");
     readBlobAsBinaryString(testFiles, testFiles['UTF8-file']);
 }
 
+function testReadingBinaryFileAsArrayBuffer(testFiles)
+{
+    log("Test reading a binary file as array buffer");
+    readBlobAsArrayBuffer(testFiles, testFiles['binary-file']);
+}
+
 function testReadingBinaryFileAsBinaryString(testFiles)
 {
     log("Test reading a binary file as binary string");
@@ -135,6 +163,7 @@ function testMultipleReads(testFiles)
 
     log("Test calling multiple read methods and only last one is processed");
     var reader = createReaderAsync();
+    reader.readAsArrayBuffer(testFiles['UTF8-file']);
     reader.readAsBinaryString(testFiles['UTF8-file']);
     reader.readAsText(testFiles['UTF8-file']);
     reader.readAsDataURL(testFiles['UTF8-file']);
diff --git a/LayoutTests/fast/files/workers/resources/worker-read-file-sync.js b/LayoutTests/fast/files/workers/resources/worker-read-file-sync.js
index f5f76eb..42030d3 100644
--- a/LayoutTests/fast/files/workers/resources/worker-read-file-sync.js
+++ b/LayoutTests/fast/files/workers/resources/worker-read-file-sync.js
@@ -1,5 +1,19 @@
 importScripts("../../resources/read-common.js", "../../resources/read-file-test-cases.js", "worker-read-common.js");
 
+// Add specific test for FileReaderSync.
+testCases.push("testMultipleReadsSync");
+
+function testMultipleReadsSync(testFiles)
+{
+    log("Test calling multiple read methods in a row");
+    var reader = createReaderSync();
+    logResult(reader.readAsArrayBuffer(testFiles['UTF8-file']));
+    logResult(reader.readAsBinaryString(testFiles['binary-file']));
+    logResult(reader.readAsDataURL(testFiles['empty-file']));
+
+    runNextTest(testFiles);
+}
+
 function isReadAsAsync()
 {
     return false;
diff --git a/LayoutTests/fast/files/workers/worker-read-blob-sync-expected.txt b/LayoutTests/fast/files/workers/worker-read-blob-sync-expected.txt
index 2ce59b2..b176781 100644
--- a/LayoutTests/fast/files/workers/worker-read-blob-sync-expected.txt
+++ b/LayoutTests/fast/files/workers/worker-read-blob-sync-expected.txt
@@ -5,38 +5,55 @@ Received exception 1: NOT_FOUND_ERR
 Test reading a blob containing existent and non-existent file
 Received exception 1: NOT_FOUND_ERR
 Test reading a blob containing empty file
-
+result size: 0
+result: 
 Test reading a blob containing empty text
-
+result size: 0
+result: 
 Test reading a blob containing empty files and empty texts
-
+result size: 0
+result: 
 Test reading a blob containing single file
-Hello
+result size: 5
+result: Hello
 Test reading a blob containing single text
-First
+result size: 5
+result: First
 Test reading a blob containing single text as data URL
-data:base64,Rmlyc3Q=
+result size: 20
+result: data:base64,Rmlyc3Q=
 Test reading a blob containing single text as data URL (optional content type provided)
-data:type/foo;base64,Rmlyc3Q=
+result size: 29
+result: data:type/foo;base64,Rmlyc3Q=
 Test reading a blob containing single ArrayBuffer
-0x0 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
+result size: 9
+result: 0x0 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
 Test reading a blob containing sliced file
-onder
+result size: 5
+result: onder
 Test reading a blob containing sliced text
-irst
+result size: 4
+result: irst
 Test reading a blob containing sliced ArrayBuffer
-0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
+result size: 8
+result: 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
 Test reading a blob containing multiple files
-HelloWonderfulWorld
+result size: 19
+result: HelloWonderfulWorld
 Test reading a blob containing multiple texts
-FirstSecondThird
+result size: 16
+result: FirstSecondThird
 Test reading a blob containing multiple ArrayBuffer
-0x0 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
+result size: 9
+result: 0x0 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
 Test reading a hybrid blob
-FirstHelloSecondWonderfulWorldThird012
+result size: 38
+result: FirstHelloSecondWonderfulWorldThird012
 Test reading a sliced hybrid blob
-lloSecondWon
+result size: 12
+result: lloSecondWon
 Test reading a triple-sliced hybrid blob
-ondWonderfulWorldThird012Foolo
+result size: 30
+result: ondWonderfulWorldThird012Foolo
 DONE
 
diff --git a/LayoutTests/fast/files/workers/worker-read-file-async-expected.txt b/LayoutTests/fast/files/workers/worker-read-file-async-expected.txt
index d0361b3..9dee0f2 100644
--- a/LayoutTests/fast/files/workers/worker-read-file-async-expected.txt
+++ b/LayoutTests/fast/files/workers/worker-read-file-async-expected.txt
@@ -1,5 +1,11 @@
 
 Received files in worker
+Test reading a non-existent file as array buffer
+readyState: 0
+Received error event
+readyState: 2
+error code: 1
+Received loadend event
 Test reading a non-existent file as binary string
 readyState: 0
 Received error event
@@ -18,6 +24,15 @@ Received error event
 readyState: 2
 error code: 1
 Received loadend event
+Test reading an empty file as array buffer
+readyState: 0
+Received loadstart event
+readyState: 1
+Received load event
+readyState: 2
+result size: 0
+result: 
+Received loadend event
 Test reading an empty file as binary string
 readyState: 0
 Received loadstart event
@@ -45,6 +60,15 @@ readyState: 2
 result size: 5
 result: data:
 Received loadend event
+Test reading a UTF-8 file as array buffer
+readyState: 0
+Received loadstart event
+readyState: 1
+Received load event
+readyState: 2
+result size: 5
+result: Hello
+Received loadend event
 Test reading a UTF-8 file as binary string
 readyState: 0
 Received loadstart event
@@ -54,6 +78,15 @@ readyState: 2
 result size: 5
 result: Hello
 Received loadend event
+Test reading a binary file as array buffer
+readyState: 0
+Received loadstart event
+readyState: 1
+Received load event
+readyState: 2
+result size: 9
+result: 0x0 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
+Received loadend event
 Test reading a binary file as binary string
 readyState: 0
 Received loadstart event
diff --git a/LayoutTests/fast/files/workers/worker-read-file-sync-expected.txt b/LayoutTests/fast/files/workers/worker-read-file-sync-expected.txt
index 3691a58..78484f0 100644
Binary files a/LayoutTests/fast/files/workers/worker-read-file-sync-expected.txt and b/LayoutTests/fast/files/workers/worker-read-file-sync-expected.txt differ
diff --git a/WebCore/Android.jscbindings.mk b/WebCore/Android.jscbindings.mk
index 72eb533..961e8f3 100644
--- a/WebCore/Android.jscbindings.mk
+++ b/WebCore/Android.jscbindings.mk
@@ -101,6 +101,7 @@ LOCAL_SRC_FILES += \
 	bindings/js/JSEventListener.cpp \
 	bindings/js/JSEventTarget.cpp \
 	bindings/js/JSExceptionBase.cpp \
+	bindings/js/JSFileReaderCustom.cpp \
 	bindings/js/JSGeolocationCustom.cpp \
 	bindings/js/JSHTMLAllCollectionCustom.cpp \
 	bindings/js/JSHTMLAppletElementCustom.cpp \
diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt
index 33f25d8..30fd99d 100644
--- a/WebCore/CMakeLists.txt
+++ b/WebCore/CMakeLists.txt
@@ -620,6 +620,7 @@ SET(WebCore_SOURCES
     bindings/js/JSEventSourceCustom.cpp
     bindings/js/JSEventTarget.cpp
     bindings/js/JSExceptionBase.cpp
+    bindings/js/JSFileReaderCustom.cpp
     bindings/js/JSGeolocationCustom.cpp
     bindings/js/JSHistoryCustom.cpp
     bindings/js/JSIDBAnyCustom.cpp
@@ -1596,6 +1597,7 @@ SET(WebCore_SOURCES
 IF (ENABLE_BLOB)
     LIST(APPEND WebCore_SOURCES
         fileapi/FileReader.cpp
+        fileapi/FileReaderLoader.cpp
         fileapi/FileThread.cpp
         fileapi/FileStreamProxy.cpp
         platform/FileStream.cpp
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 3230b2e..405a610 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,60 @@
+2010-10-29  Jian Li  <jianli at chromium.org>
+
+        Reviewed by David Levin.
+
+        Support readAsArrayBuffer in FileReader and FileReaderSync
+        https://bugs.webkit.org/show_bug.cgi?id=47691
+
+        Merge the similar code in FileReader and FileReaderSync into
+        FileReaderLoader.
+
+        Test cases have been added to read-file-test-cases.js.
+
+        * Android.jscbindings.mk:
+        * CMakeLists.txt:
+        * GNUmakefile.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/v8/custom/V8FileReaderCustom.cpp: Added.
+        * fileapi/FileReader.cpp:
+        (WebCore::FileReader::FileReader):
+        (WebCore::FileReader::readAsArrayBuffer):
+        (WebCore::FileReader::readAsBinaryString):
+        (WebCore::FileReader::readAsText):
+        (WebCore::FileReader::readAsDataURL):
+        (WebCore::FileReader::readInternal):
+        (WebCore::FileReader::doAbort):
+        (WebCore::FileReader::terminate):
+        (WebCore::FileReader::start):
+        (WebCore::FileReader::didStartLoading):
+        (WebCore::FileReader::didReceiveData):
+        (WebCore::FileReader::didFinishLoading):
+        (WebCore::FileReader::didFail):
+        (WebCore::FileReader::fireEvent):
+        (WebCore::FileReader::arrayBufferResult):
+        (WebCore::FileReader::stringResult):
+        * fileapi/FileReader.h:
+        (WebCore::FileReader::readType):
+        * fileapi/FileReader.idl:
+        * fileapi/FileReaderLoader.cpp: Added.
+        * fileapi/FileReaderLoader.h: Added.
+        * fileapi/FileReaderLoaderClient.h: Added.
+        * fileapi/FileReaderSync.cpp:
+        (WebCore::FileReaderSync::FileReaderSync):
+        (WebCore::FileReaderSync::readAsArrayBuffer):
+        (WebCore::FileReaderSync::readAsBinaryString):
+        (WebCore::FileReaderSync::readAsText):
+        (WebCore::FileReaderSync::readAsDataURL):
+        (WebCore::FileReaderSync::startLoading):
+        * fileapi/FileReaderSync.h:
+        * fileapi/FileReaderSync.idl:
+        * html/canvas/ArrayBuffer.cpp:
+        (WebCore::ArrayBuffer::create):
+        * html/canvas/ArrayBuffer.h:
+        * loader/ThreadableLoaderClient.h:
+
 2010-10-29  Tony Chang  <tony at chromium.org>
 
         Unreviewed, rolling out r70850.
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index 4b9e4fe..6c1bc35 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -728,6 +728,7 @@ webcore_sources += \
 	WebCore/bindings/js/JSEventTarget.h \
 	WebCore/bindings/js/JSExceptionBase.cpp \
 	WebCore/bindings/js/JSExceptionBase.h \
+	WebCore/bindings/js/JSFileReaderCustom.cpp \
 	WebCore/bindings/js/JSGeolocationCustom.cpp \
 	WebCore/bindings/js/JSHistoryCustom.cpp \
 	WebCore/bindings/js/JSHistoryCustom.h \
@@ -1420,6 +1421,9 @@ webcore_sources += \
 	WebCore/fileapi/FileList.h \
 	WebCore/fileapi/FileReader.cpp \
 	WebCore/fileapi/FileReader.h \
+	WebCore/fileapi/FileReaderLoader.cpp \
+	WebCore/fileapi/FileReaderLoader.h \
+	WebCore/fileapi/FileReaderLoaderClient.h \
 	WebCore/fileapi/FileReaderSync.cpp \
 	WebCore/fileapi/FileReaderSync.h \
 	WebCore/fileapi/FileStreamProxy.cpp \
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index 9fda15e..934db17 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -602,6 +602,7 @@
             'bindings/js/JSEventTarget.h',
             'bindings/js/JSExceptionBase.cpp',
             'bindings/js/JSExceptionBase.h',
+            'bindings/js/JSFileReaderCustom.cpp',
             'bindings/js/JSGeolocationCustom.cpp',
             'bindings/js/JSHistoryCustom.cpp',
             'bindings/js/JSHistoryCustom.h',
@@ -1508,6 +1509,9 @@
             'fileapi/FileList.h',
             'fileapi/FileReader.cpp',
             'fileapi/FileReader.h',
+            'fileapi/FileReaderLoader.cpp',
+            'fileapi/FileReaderLoader.h',
+            'fileapi/FileReaderLoaderClient.h',
             'fileapi/FileReaderSync.cpp',
             'fileapi/FileReaderSync.h',
             'fileapi/FileStreamProxy.cpp',
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index 61d6934..132d36d 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -420,6 +420,7 @@ v8 {
         bindings/v8/custom/V8ElementCustom.cpp \
         bindings/v8/custom/V8EventCustom.cpp \
         bindings/v8/custom/V8EventSourceConstructor.cpp \
+        bindings/v8/custom/V8FileReaderCustom.cpp \
         bindings/v8/custom/V8HTMLAllCollectionCustom.cpp
 
     contains(DEFINES, ENABLE_VIDEO=1) {
@@ -519,6 +520,7 @@ v8 {
         bindings/js/JSEventSourceCustom.cpp \
         bindings/js/JSEventTarget.cpp \
         bindings/js/JSExceptionBase.cpp \
+        bindings/js/JSFileReaderCustom.cpp \
         bindings/js/JSGeolocationCustom.cpp \
         bindings/js/JSHistoryCustom.cpp \
         bindings/js/JSHTMLAppletElementCustom.cpp \
@@ -829,6 +831,7 @@ SOURCES += \
     fileapi/File.cpp \
     fileapi/FileList.cpp \
     fileapi/FileReader.cpp \
+    fileapi/FileReaderLoader.cpp \
     fileapi/FileReaderSync.cpp \
     fileapi/FileStreamProxy.cpp \
     fileapi/FileThread.cpp \
@@ -1736,6 +1739,8 @@ HEADERS += \
     fileapi/FileException.h \
     fileapi/FileList.h \
     fileapi/FileReader.h \
+    fileapi/FileReaderLoader.h \
+    fileapi/FileReaderLoaderClient.h \
     fileapi/FileReaderSync.h \
     fileapi/FileStreamProxy.h \
     fileapi/FileThread.h \
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index a6ff69f..0f894e6 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -48836,6 +48836,18 @@
 				>
 			</File>
 			<File
+				RelativePath="..\fileapi\FileReaderLoader.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\fileapi\FileReaderLoader.h"
+				>
+			</File>
+			<File
+				RelativePath="..\fileapi\FileReaderLoaderClient.h"
+				>
+			</File>
+			<File
 				RelativePath="..\fileapi\FileReaderSync.cpp"
 				>
 			</File>
@@ -56379,6 +56391,10 @@
 					>
 				</File>
 				<File
+					RelativePath="..\bindings\js\JSFileReaderCustom.cpp"
+					>
+				</File>
+				<File
 					RelativePath="..\bindings\js\JSGeolocationCustom.cpp"
 					>
 					<FileConfiguration
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index bffcda1..6bc2e36 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -749,6 +749,10 @@
 		2E4346550F546A8200B0F1BA /* WorkerThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346430F546A8200B0F1BA /* WorkerThread.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2E4346580F546A9900B0F1BA /* CrossThreadCopier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E4346560F546A9900B0F1BA /* CrossThreadCopier.cpp */; };
 		2E4346590F546A9900B0F1BA /* CrossThreadCopier.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346570F546A9900B0F1BA /* CrossThreadCopier.h */; };
+		2E7582EE12764F260062628B /* JSFileReaderCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E7582ED12764F260062628B /* JSFileReaderCustom.cpp */; };
+		2E75841D12779ADA0062628B /* FileReaderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E75841A12779ADA0062628B /* FileReaderLoader.cpp */; };
+		2E75841E12779ADA0062628B /* FileReaderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E75841B12779ADA0062628B /* FileReaderLoader.h */; };
+		2E75841F12779ADA0062628B /* FileReaderLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E75841C12779ADA0062628B /* FileReaderLoaderClient.h */; };
 		2E94F43B119207DA00B7F75D /* JSFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E94F439119207DA00B7F75D /* JSFileReader.cpp */; };
 		2E94F43C119207DA00B7F75D /* JSFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E94F43A119207DA00B7F75D /* JSFileReader.h */; };
 		2EA768040FE7126400AB9C8A /* WorkerScriptLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EA768030FE7126400AB9C8A /* WorkerScriptLoaderClient.h */; };
@@ -6799,6 +6803,10 @@
 		2E4346430F546A8200B0F1BA /* WorkerThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WorkerThread.h; path = workers/WorkerThread.h; sourceTree = "<group>"; };
 		2E4346560F546A9900B0F1BA /* CrossThreadCopier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrossThreadCopier.cpp; sourceTree = "<group>"; };
 		2E4346570F546A9900B0F1BA /* CrossThreadCopier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadCopier.h; sourceTree = "<group>"; };
+		2E7582ED12764F260062628B /* JSFileReaderCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFileReaderCustom.cpp; sourceTree = "<group>"; };
+		2E75841A12779ADA0062628B /* FileReaderLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileReaderLoader.cpp; path = fileapi/FileReaderLoader.cpp; sourceTree = "<group>"; };
+		2E75841B12779ADA0062628B /* FileReaderLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileReaderLoader.h; path = fileapi/FileReaderLoader.h; sourceTree = "<group>"; };
+		2E75841C12779ADA0062628B /* FileReaderLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileReaderLoaderClient.h; path = fileapi/FileReaderLoaderClient.h; sourceTree = "<group>"; };
 		2E94F439119207DA00B7F75D /* JSFileReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFileReader.cpp; sourceTree = "<group>"; };
 		2E94F43A119207DA00B7F75D /* JSFileReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFileReader.h; sourceTree = "<group>"; };
 		2EA768030FE7126400AB9C8A /* WorkerScriptLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WorkerScriptLoaderClient.h; path = workers/WorkerScriptLoaderClient.h; sourceTree = "<group>"; };
@@ -15031,6 +15039,9 @@
 				4689F1AE1267BAE100E8D380 /* FileMetadata.h */,
 				976D6C69122B8A3D001FD1F7 /* FileReader.cpp */,
 				976D6C6A122B8A3D001FD1F7 /* FileReader.h */,
+				2E75841A12779ADA0062628B /* FileReaderLoader.cpp */,
+				2E75841B12779ADA0062628B /* FileReaderLoader.h */,
+				2E75841C12779ADA0062628B /* FileReaderLoaderClient.h */,
 				2EDF369A122C94B4002F7D4E /* FileReaderSync.cpp */,
 				2EDF369B122C94B4002F7D4E /* FileReaderSync.h */,
 				976D6C6C122B8A3D001FD1F7 /* FileStreamProxy.cpp */,
@@ -16973,6 +16984,7 @@
 				893C485212499B06002B3D86 /* JSEntrySyncCustom.cpp */,
 				BCEFAF4D0C317E6900FA81F6 /* JSEventCustom.cpp */,
 				BC275B8011C5D2B400C9206C /* JSEventSourceCustom.cpp */,
+				2E7582ED12764F260062628B /* JSFileReaderCustom.cpp */,
 				49EECF7210508D9C00099FAB /* JSFloat32ArrayCustom.cpp */,
 				FE80D7A60E9C1ED2000D6F75 /* JSGeolocationCustom.cpp */,
 				BCE7B1920D4E86960075A539 /* JSHistoryCustom.cpp */,
@@ -19515,6 +19527,8 @@
 				976D6C86122B8A3D001FD1F7 /* FileList.h in Headers */,
 				4689F1AF1267BAE100E8D380 /* FileMetadata.h in Headers */,
 				976D6C89122B8A3D001FD1F7 /* FileReader.h in Headers */,
+				2E75841E12779ADA0062628B /* FileReaderLoader.h in Headers */,
+				2E75841F12779ADA0062628B /* FileReaderLoaderClient.h in Headers */,
 				2EDF369D122C94B4002F7D4E /* FileReaderSync.h in Headers */,
 				2EF1BFEB121C9F4200C27627 /* FileStream.h in Headers */,
 				2EF1BFF9121CB0CE00C27627 /* FileStreamClient.h in Headers */,
@@ -22137,6 +22151,7 @@
 				F55B3DBD1251F12D003EF269 /* FileInputType.cpp in Sources */,
 				976D6C85122B8A3D001FD1F7 /* FileList.cpp in Sources */,
 				976D6C88122B8A3D001FD1F7 /* FileReader.cpp in Sources */,
+				2E75841D12779ADA0062628B /* FileReaderLoader.cpp in Sources */,
 				2EDF369C122C94B4002F7D4E /* FileReaderSync.cpp in Sources */,
 				2EF1BFEA121C9F4200C27627 /* FileStream.cpp in Sources */,
 				976D6C8B122B8A3D001FD1F7 /* FileStreamProxy.cpp in Sources */,
@@ -22569,6 +22584,7 @@
 				898785F0122E1E87003AABDA /* JSFileException.cpp in Sources */,
 				BC00F0160E0A189500FD04E3 /* JSFileList.cpp in Sources */,
 				2E94F43B119207DA00B7F75D /* JSFileReader.cpp in Sources */,
+				2E7582EE12764F260062628B /* JSFileReaderCustom.cpp in Sources */,
 				898785F4122E1EAC003AABDA /* JSFileReaderSync.cpp in Sources */,
 				898785B2122CA2A7003AABDA /* JSFileSystemCallback.cpp in Sources */,
 				46DA844D1224A0710060D006 /* JSFileWriter.cpp in Sources */,
diff --git a/WebCore/bindings/js/JSFileReaderCustom.cpp b/WebCore/bindings/js/JSFileReaderCustom.cpp
new file mode 100644
index 0000000..c771b63
--- /dev/null
+++ b/WebCore/bindings/js/JSFileReaderCustom.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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 "JSFileReader.h"
+
+#include "ArrayBuffer.h"
+#include "FileReader.h"
+#include "JSArrayBuffer.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSFileReader::result(ExecState* exec) const
+{
+    FileReader* imp = impl();
+    if (imp->readType() == FileReaderLoader::ReadAsArrayBuffer)
+        return toJS(exec, globalObject(), WTF::getPtr(imp->arrayBufferResult()));
+    return jsOwnedStringOrNull(exec, imp->stringResult());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB)
diff --git a/WebCore/bindings/v8/custom/V8FileReaderCustom.cpp b/WebCore/bindings/v8/custom/V8FileReaderCustom.cpp
index 5f4fb57..de4691f 100755
--- a/WebCore/bindings/v8/custom/V8FileReaderCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8FileReaderCustom.cpp
@@ -29,9 +29,13 @@
  */
 
 #include "config.h"
+
+#if ENABLE(BLOB)
+
 #include "V8FileReader.h"
 
 #include "ScriptExecutionContext.h"
+#include "V8ArrayBuffer.h"
 #include "V8Binding.h"
 
 namespace WebCore {
@@ -57,4 +61,16 @@ v8::Handle<v8::Value> V8FileReader::constructorCallback(const v8::Arguments& arg
     return args.Holder();
 }
 
+v8::Handle<v8::Value> V8FileReader::resultAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    INC_STATS("DOM.FileReader.result._get");
+    v8::Handle<v8::Object> holder = info.Holder();
+    FileReader* imp = V8FileReader::toNative(holder);
+    if (imp->readType() == FileReader::ReadFileAsArrayBuffer)
+        return toV8(imp->arrayBufferResult());
+    return v8StringOrNull(imp->stringResult());
+}
+
 } // namespace WebCore
+
+#endif // ENABLE(BLOB)
diff --git a/WebCore/fileapi/FileReader.cpp b/WebCore/fileapi/FileReader.cpp
index 0691b28..a54a337 100644
--- a/WebCore/fileapi/FileReader.cpp
+++ b/WebCore/fileapi/FileReader.cpp
@@ -34,21 +34,17 @@
 
 #include "FileReader.h"
 
-#include "Base64.h"
+#include "ArrayBuffer.h"
 #include "Blob.h"
-#include "BlobURL.h"
 #include "CrossThreadTask.h"
 #include "File.h"
 #include "Logging.h"
 #include "ProgressEvent.h"
-#include "ResourceError.h"
-#include "ResourceRequest.h"
-#include "ResourceResponse.h"
 #include "ScriptExecutionContext.h"
-#include "TextResourceDecoder.h"
-#include "ThreadableBlobRegistry.h"
-#include "ThreadableLoader.h"
 #include <wtf/CurrentTime.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
 
 namespace WebCore {
 
@@ -57,10 +53,7 @@ const double progressNotificationIntervalMS = 50;
 FileReader::FileReader(ScriptExecutionContext* context)
     : ActiveDOMObject(context, this)
     , m_state(None)
-    , m_readType(ReadFileAsBinaryString)
-    , m_isRawDataConverted(false)
-    , m_bytesLoaded(0)
-    , m_totalBytes(0)
+    , m_readType(FileReaderLoader::ReadAsBinaryString)
     , m_lastProgressNotificationTimeMS(0)
 {
 }
@@ -86,6 +79,16 @@ void FileReader::stop()
     terminate();
 }
 
+void FileReader::readAsArrayBuffer(Blob* blob)
+{
+    if (!blob)
+        return;
+
+    LOG(FileAPI, "FileReader: reading as array buffer: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : "");
+
+    readInternal(blob, FileReaderLoader::ReadAsArrayBuffer);
+}
+
 void FileReader::readAsBinaryString(Blob* blob)
 {
     if (!blob)
@@ -93,7 +96,7 @@ void FileReader::readAsBinaryString(Blob* blob)
 
     LOG(FileAPI, "FileReader: reading as binary: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : "");
 
-    readInternal(blob, ReadFileAsBinaryString);
+    readInternal(blob, FileReaderLoader::ReadAsBinaryString);
 }
 
 void FileReader::readAsText(Blob* blob, const String& encoding)
@@ -103,9 +106,8 @@ void FileReader::readAsText(Blob* blob, const String& encoding)
 
     LOG(FileAPI, "FileReader: reading as text: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : "");
 
-    if (!encoding.isEmpty())
-        m_encoding = TextEncoding(encoding);
-    readInternal(blob, ReadFileAsText);
+    m_encoding = encoding;
+    readInternal(blob, FileReaderLoader::ReadAsText);
 }
 
 void FileReader::readAsDataURL(Blob* blob)
@@ -115,8 +117,7 @@ void FileReader::readAsDataURL(Blob* blob)
 
     LOG(FileAPI, "FileReader: reading as data URL: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : "");
 
-    m_fileType = blob->type();
-    readInternal(blob, ReadFileAsDataURL);
+    readInternal(blob, FileReaderLoader::ReadAsDataURL);
 }
 
 static void delayedStart(ScriptExecutionContext*, FileReader* reader)
@@ -124,7 +125,7 @@ static void delayedStart(ScriptExecutionContext*, FileReader* reader)
     reader->start();
 }
 
-void FileReader::readInternal(Blob* blob, ReadType type)
+void FileReader::readInternal(Blob* blob, FileReaderLoader::ReadType type)
 {
     // readAs*** methods() can be called multiple times. Only the last call before the actual reading happens is processed.
     if (m_state != None && m_state != Starting)
@@ -159,7 +160,6 @@ void FileReader::doAbort()
 {
     terminate();
 
-    m_builder.clear();
     m_error = FileError::create(FileError::ABORT_ERR);
 
     fireEvent(eventNames().errorEvent);
@@ -171,75 +171,29 @@ void FileReader::terminate()
 {
     if (m_loader) {
         m_loader->cancel();
-        cleanup();
+        m_loader = 0;
     }
     m_state = Completed;
 }
 
-void FileReader::cleanup()
-{
-    m_loader = 0;
-    ThreadableBlobRegistry::unregisterBlobURL(m_urlForReading);
-    m_urlForReading = KURL();
-}
-
 void FileReader::start()
 {
     m_state = Opening;
 
-    // The blob is read by routing through the request handling layer given a temporary public url.
-    m_urlForReading = BlobURL::createPublicURL(scriptExecutionContext()->securityOrigin());
-    ThreadableBlobRegistry::registerBlobURL(m_urlForReading, m_blob->url());
-
-    ResourceRequest request(m_urlForReading);
-    request.setHTTPMethod("GET");
-
-    ThreadableLoaderOptions options;
-    options.sendLoadCallbacks = true;
-    options.sniffContent = false;
-    options.forcePreflight = false;
-    options.allowCredentials = true;
-    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
-
-    m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options);
+    m_loader = adoptPtr(new FileReaderLoader(m_readType, this));
+    m_loader->setEncoding(m_encoding);
+    m_loader->setDataType(m_blob->type());
+    m_loader->start(scriptExecutionContext(), m_blob.get());
 }
 
-void FileReader::didReceiveResponse(const ResourceResponse& response)
+void FileReader::didStartLoading()
 {
-    if (response.httpStatusCode() != 200) {
-        failed(response.httpStatusCode());
-        return;
-    }
-
     m_state = Reading;
     fireEvent(eventNames().loadstartEvent);
-
-    m_totalBytes = response.expectedContentLength();
 }
 
-void FileReader::didReceiveData(const char* data, int lengthReceived)
+void FileReader::didReceiveData()
 {
-    ASSERT(data && lengthReceived);
-
-    // Bail out if we have aborted the reading.
-    if (m_state == Completed)
-        return;
-
-    switch (m_readType) {
-    case ReadFileAsBinaryString:
-        m_builder.append(data, static_cast<unsigned>(lengthReceived));
-        break;
-    case ReadFileAsText:
-    case ReadFileAsDataURL:
-        m_rawData.append(data, static_cast<unsigned>(lengthReceived));
-        m_isRawDataConverted = false;
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-
-    m_bytesLoaded += lengthReceived;
-
     // Fire the progress event at least every 50ms.
     double now = WTF::currentTimeMS();
     if (!m_lastProgressNotificationTimeMS)
@@ -250,53 +204,33 @@ void FileReader::didReceiveData(const char* data, int lengthReceived)
     }
 }
 
-void FileReader::didFinishLoading(unsigned long)
+void FileReader::didFinishLoading()
 {
     m_state = Completed;
 
     fireEvent(eventNames().loadEvent);
     fireEvent(eventNames().loadendEvent);
-
-    cleanup();
 }
 
-void FileReader::didFail(const ResourceError&)
+void FileReader::didFail(int errorCode)
 {
     // If we're aborting, do not proceed with normal error handling since it is covered in aborting code.
     if (m_state == Aborting)
         return;
 
-    // Treat as internal error.
-    failed(500);
-}
-
-void FileReader::failed(int httpStatusCode)
-{
     m_state = Completed;
 
-    m_error = FileError::create(httpStatusCodeToErrorCode(httpStatusCode));
+    m_error = FileError::create(static_cast<FileError::ErrorCode>(errorCode));
     fireEvent(eventNames().errorEvent);
     fireEvent(eventNames().loadendEvent);
-
-    cleanup();
-}
-
-FileError::ErrorCode FileReader::httpStatusCodeToErrorCode(int httpStatusCode)
-{
-    switch (httpStatusCode) {
-        case 403:
-            return FileError::SECURITY_ERR;
-        case 404:
-            return FileError::NOT_FOUND_ERR;
-        default:
-            return FileError::NOT_READABLE_ERR;
-    }
 }
 
 void FileReader::fireEvent(const AtomicString& type)
 {
     // FIXME: the current ProgressEvent uses "unsigned long" for total and loaded attributes. Need to talk with the spec writer to resolve the issue.
-    dispatchEvent(ProgressEvent::create(type, true, static_cast<unsigned>(m_bytesLoaded), static_cast<unsigned>(m_totalBytes)));
+    unsigned bytesLoaded = m_loader ? m_loader->bytesLoaded() : 0;
+    unsigned totalBytes = m_loader ? m_loader->totalBytes() : 0;
+    dispatchEvent(ProgressEvent::create(type, true, bytesLoaded, totalBytes));
 }
 
 FileReader::ReadyState FileReader::readyState() const
@@ -316,65 +250,14 @@ FileReader::ReadyState FileReader::readyState() const
     return EMPTY;
 }
 
-String FileReader::result()
+PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const
 {
-    // If reading as binary string, we can return the result immediately.
-    if (m_readType == ReadFileAsBinaryString)
-        return m_builder.toString();
-
-    // If we already convert the raw data received so far, we can return the result now.
-    if (m_isRawDataConverted)
-        return m_builder.toString();
-    m_isRawDataConverted = true;
-
-    if (m_readType == ReadFileAsText)
-        convertToText();
-    // For data URL, we only do the coversion until we receive all the raw data.
-    else if (m_readType == ReadFileAsDataURL && m_state == Completed)
-        convertToDataURL(m_rawData, m_fileType, m_builder);
-
-    return m_builder.toString();
+    return m_loader ? m_loader->arrayBufferResult() : 0;
 }
 
-void FileReader::convertToText()
+String FileReader::stringResult()
 {
-    if (!m_rawData.size()) {
-        m_builder.clear();
-        return;
-    }
-
-    // Decode the data.
-    // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this
-    // requirement in order to be consistent with how WebKit decodes the web content: always has the BOM override the
-    // provided encoding.     
-    // FIXME: consider supporting incremental decoding to improve the perf.
-    if (!m_decoder)
-        m_decoder = TextResourceDecoder::create("text/plain", m_encoding.isValid() ? m_encoding : UTF8Encoding());
-    m_builder.clear();
-    m_builder.append(m_decoder->decode(&m_rawData.at(0), m_rawData.size()));
-
-    if (m_state == Completed && !m_error)
-        m_builder.append(m_decoder->flush());
-}
-
-void FileReader::convertToDataURL(const Vector<char>& rawData, const String& fileType, StringBuilder& builder)
-{
-    builder.clear();
-    builder.append("data:");
-
-    if (!rawData.size())
-        return;
-
-    if (!fileType.isEmpty()) {
-        builder.append(fileType);
-        builder.append(";base64,");
-    } else
-        builder.append("base64,");
-
-    Vector<char> out;
-    base64Encode(rawData, out);
-    out.append('\0');
-    builder.append(out.data());
+    return m_loader ? m_loader->stringResult() : "";
 }
 
 } // namespace WebCore
diff --git a/WebCore/fileapi/FileReader.h b/WebCore/fileapi/FileReader.h
index 3f76ad6..04513f3 100644
--- a/WebCore/fileapi/FileReader.h
+++ b/WebCore/fileapi/FileReader.h
@@ -36,24 +36,19 @@
 #include "ActiveDOMObject.h"
 #include "EventTarget.h"
 #include "FileError.h"
-#include "KURL.h"
-#include "TextEncoding.h"
-#include "ThreadableLoaderClient.h"
-#include <wtf/PassRefPtr.h>
+#include "FileReaderLoader.h"
+#include "FileReaderLoaderClient.h"
+#include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-#include <wtf/text/StringBuilder.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
+class ArrayBuffer;
 class Blob;
 class ScriptExecutionContext;
-class TextResourceDecoder;
-class ThreadableLoader;
 
-class FileReader : public RefCounted<FileReader>, public ActiveDOMObject, public EventTarget, public ThreadableLoaderClient {
+class FileReader : public RefCounted<FileReader>, public ActiveDOMObject, public EventTarget, public FileReaderLoaderClient {
 public:
     static PassRefPtr<FileReader> create(ScriptExecutionContext* context)
     {
@@ -68,6 +63,7 @@ public:
         DONE = 2
     };
 
+    void readAsArrayBuffer(Blob*);
     void readAsBinaryString(Blob*);
     void readAsText(Blob*, const String& encoding = "");
     void readAsDataURL(Blob*);
@@ -78,11 +74,9 @@ public:
 
     ReadyState readyState() const;
     PassRefPtr<FileError> error() { return m_error; }
-    String result();
-
-    // Helper methods, also used by FileReaderSync.
-    static FileError::ErrorCode httpStatusCodeToErrorCode(int httpStatusCode);
-    static void convertToDataURL(const Vector<char>& rawData, const String& fileType, StringBuilder&);
+    FileReaderLoader::ReadType readType() const { return m_readType; }
+    PassRefPtr<ArrayBuffer> arrayBufferResult() const;
+    String stringResult();
 
     // ActiveDOMObject
     virtual bool canSuspend() const;
@@ -93,11 +87,11 @@ public:
     virtual FileReader* toFileReader() { return this; }
     virtual ScriptExecutionContext* scriptExecutionContext() const { return ActiveDOMObject::scriptExecutionContext(); }
 
-    // ThreadableLoaderClient
-    virtual void didReceiveResponse(const ResourceResponse&);
-    virtual void didReceiveData(const char*, int);
-    virtual void didFinishLoading(unsigned long identifier);
-    virtual void didFail(const ResourceError&);
+    // FileReaderLoaderClient
+    virtual void didStartLoading();
+    virtual void didReceiveData();
+    virtual void didFinishLoading();
+    virtual void didFail(int errorCode);
 
     using RefCounted<FileReader>::ref;
     using RefCounted<FileReader>::deref;
@@ -110,11 +104,6 @@ public:
     DEFINE_ATTRIBUTE_EVENT_LISTENER(loadend);
 
 private:
-    enum ReadType {
-        ReadFileAsBinaryString,
-        ReadFileAsText,
-        ReadFileAsDataURL
-    };
     enum InternalState {
         None,
         Starting,
@@ -133,38 +122,19 @@ private:
     virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; }
 
     void terminate();
-    void cleanup();
-    void readInternal(Blob*, ReadType);
-    void failed(int httpStatusCode);
+    void readInternal(Blob*, FileReaderLoader::ReadType);
     void fireErrorEvent(int httpStatusCode);
     void fireEvent(const AtomicString& type);
-    void convertToText();
-    void convertToDataURL();
 
     InternalState m_state;
     EventTargetData m_eventTargetData;
 
     RefPtr<Blob> m_blob;
-    KURL m_urlForReading;
-    ReadType m_readType;
-    TextEncoding m_encoding;
-
-    StringBuilder m_builder;
-
-    // The raw data. We have to keep track of all the raw data for it to be converted to text or data URL data.
-    Vector<char> m_rawData;
-    bool m_isRawDataConverted;
-
-    // The decoder used to decode the text data.
-    RefPtr<TextResourceDecoder> m_decoder;
-
-    // Needed to create data URL.
-    String m_fileType;
+    FileReaderLoader::ReadType m_readType;
+    String m_encoding;
 
-    RefPtr<ThreadableLoader> m_loader;
+    OwnPtr<FileReaderLoader> m_loader;
     RefPtr<FileError> m_error;
-    long long m_bytesLoaded;
-    long long m_totalBytes;
     double m_lastProgressNotificationTimeMS;
 };
 
diff --git a/WebCore/fileapi/FileReader.idl b/WebCore/fileapi/FileReader.idl
index febb231..ebc6ffd 100644
--- a/WebCore/fileapi/FileReader.idl
+++ b/WebCore/fileapi/FileReader.idl
@@ -44,6 +44,7 @@ module html {
         readonly attribute unsigned short readyState;
 
         // async read methods
+        void readAsArrayBuffer(in Blob blob);
         void readAsBinaryString(in Blob blob);
         void readAsText(in Blob blob, in [Optional] DOMString encoding);
         void readAsDataURL(in Blob blob);
@@ -51,7 +52,7 @@ module html {
         void abort();
 
         // file data
-        readonly attribute [ConvertScriptString] DOMString result;
+        readonly attribute [Custom] DOMObject result;
 
         readonly attribute FileError error;
 
diff --git a/WebCore/fileapi/FileReaderLoader.cpp b/WebCore/fileapi/FileReaderLoader.cpp
new file mode 100644
index 0000000..dcd5860
--- /dev/null
+++ b/WebCore/fileapi/FileReaderLoader.cpp
@@ -0,0 +1,302 @@
+/*
+ * 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 "FileReaderLoader.h"
+
+#include "ArrayBuffer.h"
+#include "Base64.h"
+#include "Blob.h"
+#include "BlobURL.h"
+#include "FileReaderLoaderClient.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+#include "ScriptExecutionContext.h"
+#include "TextResourceDecoder.h"
+#include "ThreadableBlobRegistry.h"
+#include "ThreadableLoader.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+FileReaderLoader::FileReaderLoader(ReadType readType, FileReaderLoaderClient* client)
+    : m_readType(readType)
+    , m_client(client)
+    , m_isRawDataConverted(false)
+    , m_stringResult("")
+    , m_bytesLoaded(0)
+    , m_totalBytes(0)
+    , m_errorCode(0)
+{
+}
+
+FileReaderLoader::~FileReaderLoader()
+{
+    terminate();
+    ThreadableBlobRegistry::unregisterBlobURL(m_urlForReading);
+}
+
+void FileReaderLoader::start(ScriptExecutionContext* scriptExecutionContext, Blob* blob)
+{
+    // The blob is read by routing through the request handling layer given a temporary public url.
+    m_urlForReading = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin());
+    ThreadableBlobRegistry::registerBlobURL(m_urlForReading, blob->url());
+
+    // Construct and load the request.
+    ResourceRequest request(m_urlForReading);
+    request.setHTTPMethod("GET");
+
+    ThreadableLoaderOptions options;
+    options.sendLoadCallbacks = true;
+    options.sniffContent = false;
+    options.forcePreflight = false;
+    options.allowCredentials = true;
+    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
+
+    if (m_client)
+        m_loader = ThreadableLoader::create(scriptExecutionContext, this, request, options);
+    else
+        ThreadableLoader::loadResourceSynchronously(scriptExecutionContext, request, *this, options);
+}
+
+void FileReaderLoader::cancel()
+{
+    m_errorCode = FileError::ABORT_ERR;
+    terminate();
+}
+
+void FileReaderLoader::terminate()
+{
+    if (m_loader) {
+        m_loader->cancel();
+        cleanup();
+    }
+}
+
+void FileReaderLoader::cleanup()
+{
+    m_loader = 0;
+
+    // If we get any error, we do not need to keep a buffer around.
+    if (m_errorCode) {
+        m_rawData = 0;
+        m_stringResult = "";
+    }
+}
+
+void FileReaderLoader::didReceiveResponse(const ResourceResponse& response)
+{
+    if (response.httpStatusCode() != 200) {
+        failed(httpStatusCodeToErrorCode(response.httpStatusCode()));
+        return;
+    }
+
+    // FIXME: Support reading more than the current size limit of ArrayBuffer.
+    if (static_cast<unsigned long long>(response.expectedContentLength()) >  std::numeric_limits<unsigned>::max()) {
+        failed(FileError::NOT_READABLE_ERR);
+        return;
+    }
+    m_totalBytes = static_cast<unsigned>(response.expectedContentLength());
+
+    ASSERT(!m_rawData);
+    m_rawData = ArrayBuffer::create(static_cast<unsigned>(m_totalBytes), 1);
+
+    if (m_client)
+        m_client->didStartLoading();
+}
+
+void FileReaderLoader::didReceiveData(const char* data, int lengthReceived)
+{
+    ASSERT(data && lengthReceived > 0);
+
+    // Bail out if we encounter an error.
+    if (m_errorCode)
+        return;
+
+    memcpy(static_cast<char*>(m_rawData->data()) + static_cast<unsigned>(m_bytesLoaded), data, static_cast<unsigned>(lengthReceived));
+    m_bytesLoaded += static_cast<unsigned>(lengthReceived);
+
+    m_isRawDataConverted = false;
+
+    if (m_client)
+        m_client->didReceiveData();
+}
+
+void FileReaderLoader::didFinishLoading(unsigned long)
+{
+    cleanup();
+    if (m_client)
+        m_client->didFinishLoading();
+}
+
+void FileReaderLoader::didFail(const ResourceError&)
+{
+    // If we're aborting, do not proceed with normal error handling since it is covered in aborting code.
+    if (m_errorCode == FileError::ABORT_ERR)
+        return;
+
+    failed(FileError::NOT_READABLE_ERR);
+}
+
+void FileReaderLoader::failed(int errorCode)
+{
+    m_errorCode = errorCode;
+    cleanup();
+    if (m_client)
+        m_client->didFail(m_errorCode);
+}
+
+FileError::ErrorCode FileReaderLoader::httpStatusCodeToErrorCode(int httpStatusCode)
+{
+    switch (httpStatusCode) {
+    case 403:
+        return FileError::SECURITY_ERR;
+    case 404:
+        return FileError::NOT_FOUND_ERR;
+    default:
+        return FileError::NOT_READABLE_ERR;
+    }
+}
+
+PassRefPtr<ArrayBuffer> FileReaderLoader::arrayBufferResult() const
+{
+    ASSERT(m_readType == ReadAsArrayBuffer);
+
+    // If the loading is not started or an error occurs, return an empty result.
+    if (!m_rawData || m_errorCode)
+        return 0;
+
+    // If completed, we can simply return our buffer.
+    if (isCompleted())
+        return m_rawData;
+
+    // Otherwise, return a copy.
+    return ArrayBuffer::create(m_rawData.get());
+}
+
+String FileReaderLoader::stringResult()
+{
+    ASSERT(m_readType != ReadAsArrayBuffer);
+
+    // If the loading is not started or an error occurs, return an empty result.
+    if (!m_rawData || m_errorCode)
+        return m_stringResult;
+
+    // If already converted from the raw data, return the result now.
+    if (m_isRawDataConverted)
+        return m_stringResult;
+
+    switch (m_readType) {
+    case ReadAsArrayBuffer:
+        // No conversion is needed.
+        break;
+    case ReadAsBinaryString:
+        m_stringResult = String(static_cast<const char*>(m_rawData->data()), m_bytesLoaded);
+        break;
+    case ReadAsText:
+        convertToText();
+        break;
+    case ReadAsDataURL:
+        // Partial data is not supported when reading as data URL.
+        if (isCompleted())
+            convertToDataURL();
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    
+    return m_stringResult;
+}
+
+void FileReaderLoader::convertToText()
+{
+    if (!m_bytesLoaded)
+        return;
+
+    // Decode the data.
+    // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this
+    // requirement in order to be consistent with how WebKit decodes the web content: always has the BOM override the
+    // provided encoding.     
+    // FIXME: consider supporting incremental decoding to improve the perf.
+    StringBuilder builder;
+    if (!m_decoder)
+        m_decoder = TextResourceDecoder::create("text/plain", m_encoding.isValid() ? m_encoding : UTF8Encoding());
+    builder.append(m_decoder->decode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded));
+
+    if (isCompleted())
+        builder.append(m_decoder->flush());
+
+    m_stringResult = builder.toString();
+}
+
+void FileReaderLoader::convertToDataURL()
+{
+    StringBuilder builder;
+    builder.append("data:");
+
+    if (!m_bytesLoaded) {
+        m_stringResult = builder.toString();
+        return;
+    }
+
+    if (!m_dataType.isEmpty()) {
+        builder.append(m_dataType);
+        builder.append(";base64,");
+    } else
+        builder.append("base64,");
+
+    Vector<char> out;
+    base64Encode(static_cast<const char*>(m_rawData->data()), m_bytesLoaded, out);
+    out.append('\0');
+    builder.append(out.data());
+
+    m_stringResult = builder.toString();
+}
+
+bool FileReaderLoader::isCompleted() const
+{
+    return m_bytesLoaded == m_totalBytes;
+}
+
+void FileReaderLoader::setEncoding(const String& encoding)
+{
+    if (!encoding.isEmpty())
+        m_encoding = TextEncoding(encoding);
+}
+
+} // namespace WebCore
+ 
+#endif // ENABLE(BLOB)
diff --git a/WebCore/fileapi/FileReaderLoader.h b/WebCore/fileapi/FileReaderLoader.h
new file mode 100644
index 0000000..a15ee01
--- /dev/null
+++ b/WebCore/fileapi/FileReaderLoader.h
@@ -0,0 +1,119 @@
+/*
+ * 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 FileReaderLoader_h
+#define FileReaderLoader_h
+
+#if ENABLE(BLOB)
+
+#include "FileError.h"
+#include "KURL.h"
+#include "TextEncoding.h"
+#include "ThreadableLoaderClient.h"
+#include <wtf/Forward.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class ArrayBuffer;
+class Blob;
+class FileReaderLoaderClient;
+class ScriptExecutionContext;
+class TextResourceDecoder;
+class ThreadableLoader;
+
+class FileReaderLoader : public ThreadableLoaderClient {
+public:
+    enum ReadType {
+        ReadAsArrayBuffer,
+        ReadAsBinaryString,
+        ReadAsText,
+        ReadAsDataURL
+    };
+
+    // If client is given, do the loading asynchronously. Otherwise, load synchronously.
+    FileReaderLoader(ReadType, FileReaderLoaderClient*);
+    ~FileReaderLoader();
+
+    void start(ScriptExecutionContext*, Blob*);
+    void cancel();
+
+    // ThreadableLoaderClient
+    virtual void didReceiveResponse(const ResourceResponse&);
+    virtual void didReceiveData(const char*, int);
+    virtual void didFinishLoading(unsigned long identifier);
+    virtual void didFail(const ResourceError&);
+
+    String stringResult();
+    PassRefPtr<ArrayBuffer> arrayBufferResult() const;
+    unsigned bytesLoaded() const { return m_bytesLoaded; }
+    unsigned totalBytes() const { return m_totalBytes; }
+    int errorCode() const { return m_errorCode; }
+
+    void setEncoding(const String&);
+    void setDataType(const String& dataType) { m_dataType = dataType; }
+    
+private:
+    void terminate();
+    void cleanup();
+    void failed(int errorCode);
+    void convertToText();
+    void convertToDataURL();
+
+    bool isCompleted() const;
+
+    static FileError::ErrorCode httpStatusCodeToErrorCode(int);
+
+    ReadType m_readType;
+    FileReaderLoaderClient* m_client;
+    TextEncoding m_encoding;
+    String m_dataType;
+
+    KURL m_urlForReading;
+    RefPtr<ThreadableLoader> m_loader;
+
+    RefPtr<ArrayBuffer> m_rawData;
+    bool m_isRawDataConverted;
+
+    String m_stringResult;
+
+    // The decoder used to decode the text data.
+    RefPtr<TextResourceDecoder> m_decoder;
+
+    unsigned m_bytesLoaded;
+    unsigned m_totalBytes;
+    int m_errorCode;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB)
+
+#endif // FileReaderLoader_h
diff --git a/WebCore/fileapi/FileReaderLoaderClient.h b/WebCore/fileapi/FileReaderLoaderClient.h
new file mode 100644
index 0000000..4acb8ad
--- /dev/null
+++ b/WebCore/fileapi/FileReaderLoaderClient.h
@@ -0,0 +1,52 @@
+/*
+ * 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 FileReaderLoaderClient_h
+#define FileReaderLoaderClient_h
+
+#if ENABLE(BLOB)
+
+namespace WebCore {
+
+class FileReaderLoaderClient {
+public:
+    virtual ~FileReaderLoaderClient() {}
+
+    virtual void didStartLoading() = 0;
+    virtual void didReceiveData() = 0;
+    virtual void didFinishLoading() = 0;
+    virtual void didFail(int errorCode) = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(BLOB)
+
+#endif // FileReaderLoaderClient_h
diff --git a/WebCore/fileapi/FileReaderSync.cpp b/WebCore/fileapi/FileReaderSync.cpp
index 99f5a89..85e7f52 100644
--- a/WebCore/fileapi/FileReaderSync.cpp
+++ b/WebCore/fileapi/FileReaderSync.cpp
@@ -34,162 +34,66 @@
 
 #include "FileReaderSync.h"
 
-#include "Base64.h"
+#include "ArrayBuffer.h"
 #include "Blob.h"
 #include "BlobURL.h"
 #include "FileException.h"
-#include "FileReader.h"
-#include "ResourceRequest.h"
-#include "ResourceResponse.h"
-#include "ScriptExecutionContext.h"
-#include "TextEncoding.h"
-#include "TextResourceDecoder.h"
-#include "ThreadableBlobRegistry.h"
-#include "ThreadableLoader.h"
+#include "FileReaderLoader.h"
+#include <wtf/PassRefPtr.h>
 
 namespace WebCore {
 
-class FileReaderSyncLoader : public ThreadableLoaderClient {
-public:
-    // If the output result is provided, use it. Otherwise, save it as the raw data.
-    FileReaderSyncLoader(StringBuilder*);
-
-    // Returns the http status code.
-    void start(ScriptExecutionContext*, const ResourceRequest&, ExceptionCode&);
-
-    // ThreadableLoaderClient
-    virtual void didReceiveResponse(const ResourceResponse&);
-    virtual void didReceiveData(const char*, int);
-    virtual void didFinishLoading(unsigned long identifier);
-    virtual void didFail(const ResourceError&);
-
-    const Vector<char>& rawData() const { return m_rawData; }
-
-private:
-    // The output result. The caller provides this in order to load the binary data directly.
-    StringBuilder* m_builder;
-
-    // The raw data. The caller does not provide the above output result and we need to save it here.
-    Vector<char> m_rawData;
-
-    int m_httpStatusCode;    
-};
-
-FileReaderSyncLoader::FileReaderSyncLoader(StringBuilder* builder)
-    : m_builder(builder)
-    , m_httpStatusCode(0)
-{
-}
-
-void FileReaderSyncLoader::start(ScriptExecutionContext* scriptExecutionContext, const ResourceRequest& request, ExceptionCode& ec)
+FileReaderSync::FileReaderSync()
 {
-    ThreadableLoaderOptions options;
-    options.sendLoadCallbacks = true;
-    options.sniffContent = false;
-    options.forcePreflight = false;
-    options.allowCredentials = true;
-    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
-
-    ThreadableLoader::loadResourceSynchronously(scriptExecutionContext, request, *this, options);
-
-    ec = (m_httpStatusCode == 200) ? 0 : FileException::ErrorCodeToExceptionCode(FileReader::httpStatusCodeToErrorCode(m_httpStatusCode));
 }
 
-void FileReaderSyncLoader::didReceiveResponse(const ResourceResponse& response)
+PassRefPtr<ArrayBuffer> FileReaderSync::readAsArrayBuffer(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec)
 {
-    m_httpStatusCode = response.httpStatusCode();
-}
+    if (!blob)
+        return 0;
 
-void FileReaderSyncLoader::didReceiveData(const char* data, int lengthReceived)
-{
-    if (m_builder)
-        m_builder->append(data, static_cast<unsigned>(lengthReceived));
-    else
-        m_rawData.append(data, static_cast<unsigned>(lengthReceived));
-}
+    FileReaderLoader loader(FileReaderLoader::ReadAsArrayBuffer, 0);
+    startLoading(scriptExecutionContext, loader, blob, ec);
 
-void FileReaderSyncLoader::didFinishLoading(unsigned long)
-{
-}
-
-void FileReaderSyncLoader::didFail(const ResourceError&)
-{
-    // Treat as internal error.
-    m_httpStatusCode = 500;
+    return loader.arrayBufferResult();
 }
 
 String FileReaderSync::readAsBinaryString(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec)
 {
     if (!blob)
-        return m_builder.toString();
+        return String();
 
-    read(scriptExecutionContext, blob, ReadAsBinaryString, ec);
-    return m_builder.toString();
+    FileReaderLoader loader(FileReaderLoader::ReadAsBinaryString, 0);
+    startLoading(scriptExecutionContext, loader, blob, ec);
+    return loader.stringResult();
 }
 
 String FileReaderSync::readAsText(ScriptExecutionContext* scriptExecutionContext, Blob* blob, const String& encoding, ExceptionCode& ec)
 {
     if (!blob)
-        return m_builder.toString();
+        return String();
 
-    m_encoding = encoding;
-    read(scriptExecutionContext, blob, ReadAsText, ec);
-    return m_builder.toString();
+    FileReaderLoader loader(FileReaderLoader::ReadAsText, 0);
+    loader.setEncoding(encoding);
+    startLoading(scriptExecutionContext, loader, blob, ec);
+    return loader.stringResult();
 }
 
 String FileReaderSync::readAsDataURL(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec)
 {
     if (!blob)
-        return m_builder.toString();
+        return String();
 
-    read(scriptExecutionContext, blob, ReadAsDataURL, ec);
-    return m_builder.toString();
-}
-
-void FileReaderSync::read(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ReadType readType, ExceptionCode& ec)
-{
-    // The blob is read by routing through the request handling layer given the temporary public url.
-    KURL urlForReading = BlobURL::createPublicURL(scriptExecutionContext->securityOrigin());
-    ThreadableBlobRegistry::registerBlobURL(urlForReading, blob->url());
-
-    ResourceRequest request(urlForReading);
-    request.setHTTPMethod("GET");
-
-    FileReaderSyncLoader loader((readType == ReadAsBinaryString) ? &m_builder : 0);
-    loader.start(scriptExecutionContext, request, ec);
-    ThreadableBlobRegistry::unregisterBlobURL(urlForReading);
-    if (ec)
-        return;
-
-    switch (readType) {
-    case ReadAsBinaryString:
-        // Nothing to do since we need no conversion.
-        return;
-    case ReadAsText:
-        convertToText(loader.rawData().data(), loader.rawData().size(), m_builder);
-        return;
-    case ReadAsDataURL:
-        FileReader::convertToDataURL(loader.rawData(), blob->type(), m_builder);
-        return;
-    }
-
-    ASSERT_NOT_REACHED();
+    FileReaderLoader loader(FileReaderLoader::ReadAsDataURL, 0);
+    loader.setDataType(blob->type());
+    startLoading(scriptExecutionContext, loader, blob, ec);
+    return loader.stringResult();
 }
 
-void FileReaderSync::convertToText(const char* data, int size, StringBuilder& builder)
+void FileReaderSync::startLoading(ScriptExecutionContext* scriptExecutionContext, FileReaderLoader& loader, Blob* blob, ExceptionCode& ec)
 {
-    if (!size)
-        return;
-
-    // Decode the data.
-    // The File API spec says that we should use the supplied encoding if it is valid. However, we choose to ignore this
-    // requirement in order to be consistent with how WebKit decodes the web content: always have the BOM override the
-    // provided encoding.     
-    // FIXME: consider supporting incremental decoding to improve the perf.
-    RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", m_encoding.isEmpty() ? UTF8Encoding() : TextEncoding(m_encoding));
-    builder.clear();
-    builder.append(decoder->decode(data, size));
-    builder.append(decoder->flush());
+    loader.start(scriptExecutionContext, blob);
+    ec = FileException::ErrorCodeToExceptionCode(loader.errorCode());
 }
 
 } // namespace WebCore
diff --git a/WebCore/fileapi/FileReaderSync.h b/WebCore/fileapi/FileReaderSync.h
index cb0e00d..79b637f 100644
--- a/WebCore/fileapi/FileReaderSync.h
+++ b/WebCore/fileapi/FileReaderSync.h
@@ -34,13 +34,15 @@
 #if ENABLE(BLOB)
 
 #include "ExceptionCode.h"
-#include <wtf/PassRefPtr.h>
+#include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
-#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
+class ArrayBuffer;
 class Blob;
+class FileReaderLoader;
 class ScriptExecutionContext;
 
 class FileReaderSync : public RefCounted<FileReaderSync> {
@@ -52,6 +54,7 @@ public:
 
     virtual ~FileReaderSync() { }
 
+    PassRefPtr<ArrayBuffer> readAsArrayBuffer(ScriptExecutionContext*, Blob*, ExceptionCode&);
     String readAsBinaryString(ScriptExecutionContext*, Blob*, ExceptionCode&);
     String readAsText(ScriptExecutionContext* scriptExecutionContext, Blob* blob, ExceptionCode& ec)
     {
@@ -61,20 +64,9 @@ public:
     String readAsDataURL(ScriptExecutionContext*, Blob*, ExceptionCode&);
 
 private:
-    enum ReadType {
-        ReadAsBinaryString,
-        ReadAsText,
-        ReadAsDataURL
-    };
+    FileReaderSync();
 
-    FileReaderSync() { }
-
-    void read(ScriptExecutionContext*, Blob*, ReadType, ExceptionCode&);
-    void convertToText(const char* data, int size, StringBuilder&);
-
-    StringBuilder m_builder;
-
-    String m_encoding;
+    void startLoading(ScriptExecutionContext*, FileReaderLoader&, Blob*, ExceptionCode&);
 };
 
 } // namespace WebCore
diff --git a/WebCore/fileapi/FileReaderSync.idl b/WebCore/fileapi/FileReaderSync.idl
index 72818b1..381d483 100644
--- a/WebCore/fileapi/FileReaderSync.idl
+++ b/WebCore/fileapi/FileReaderSync.idl
@@ -34,6 +34,8 @@ module html {
         CanBeConstructed,
         NoStaticTables
     ] FileReaderSync {
+        [CallWith=ScriptExecutionContext] ArrayBuffer readAsArrayBuffer(in Blob blob)
+            raises(FileException);
         [CallWith=ScriptExecutionContext, ConvertScriptString] DOMString readAsBinaryString(in Blob blob)
             raises(FileException);
         [CallWith=ScriptExecutionContext, ConvertScriptString] DOMString readAsText(in Blob blob, in [Optional] DOMString encoding)
diff --git a/WebCore/html/canvas/ArrayBuffer.cpp b/WebCore/html/canvas/ArrayBuffer.cpp
index 014cc1e..ee8f149 100644
--- a/WebCore/html/canvas/ArrayBuffer.cpp
+++ b/WebCore/html/canvas/ArrayBuffer.cpp
@@ -43,11 +43,16 @@ PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned eleme
 
 PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other)
 {
-    void* data = tryAllocate(other->byteLength(), 1);
+    return ArrayBuffer::create(other->data(), other->byteLength());
+}
+
+PassRefPtr<ArrayBuffer> ArrayBuffer::create(void* source, unsigned byteLength)
+{
+    void* data = tryAllocate(byteLength, 1);
     if (!data)
         return 0;
-    RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(data, other->byteLength()));
-    memcpy(buffer->data(), other->data(), other->byteLength());
+    RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(data, byteLength));
+    memcpy(buffer->data(), source, byteLength);
     return buffer.release();
 }
 
diff --git a/WebCore/html/canvas/ArrayBuffer.h b/WebCore/html/canvas/ArrayBuffer.h
index f538080..ff5e599 100644
--- a/WebCore/html/canvas/ArrayBuffer.h
+++ b/WebCore/html/canvas/ArrayBuffer.h
@@ -35,6 +35,7 @@ class ArrayBuffer : public RefCounted<ArrayBuffer> {
   public:
     static PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
     static PassRefPtr<ArrayBuffer> create(ArrayBuffer*);
+    static PassRefPtr<ArrayBuffer> create(void* source, unsigned byteLength);
 
     void* data();
     const void* data() const;
diff --git a/WebCore/loader/ThreadableLoaderClient.h b/WebCore/loader/ThreadableLoaderClient.h
index b8a6584..bcf68be 100644
--- a/WebCore/loader/ThreadableLoaderClient.h
+++ b/WebCore/loader/ThreadableLoaderClient.h
@@ -31,6 +31,8 @@
 #ifndef ThreadableLoaderClient_h
 #define ThreadableLoaderClient_h
 
+#include <wtf/Noncopyable.h>
+
 namespace WebCore {
 
     class ResourceError;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list