Changeset 66452 in webkit


Ignore:
Timestamp:
Aug 30, 2010 9:45:21 PM (14 years ago)
Author:
jianli@chromium.org
Message:

Switch the Blob implementation to using the blob data registration model
https://bugs.webkit.org/show_bug.cgi?id=44389

Reviewed by Darin Fisher.

WebCore:

Tests: fast/files/read-blob-async.html

fast/files/read-file-async.html

With this switch, File/Blob/BlobBuilder are changed to register the blob
data. FileReader is changed to route through loading the blob resource.
FormData is also updated to take BlobData. The WebKit mac implementation
is updated to resolve the blob references in the BlobData.

  • CMakeLists.txt: Update the project file to remove BlobItem.*.
  • GNUmakefile.am: Update the project file to remove BlobItem.*.
  • WebCore.gypi: Update the project file to remove BlobItem.*.
  • WebCore.pro: Update the project file to remove BlobItem.*.
  • WebCore.vcproj/WebCore.vcproj: Update the project file to remove BlobItem.*.
  • WebCore.xcodeproj/project.pbxproj: Update the project file to remove BlobItem.*.
  • fileapi/Blob.cpp: Switch to using BlobData.

(WebCore::Blob::Blob):
(WebCore::Blob::slice):

  • fileapi/Blob.h: Switch to using BlobData.

(WebCore::Blob::create):
(WebCore::Blob::size):
(WebCore::Blob::isFile):

  • fileapi/BlobBuilder.cpp: Switch to using BlobData.

(WebCore::BlobBuilder::BlobBuilder):
(WebCore::BlobBuilder::append):
(WebCore::BlobBuilder::getBlob):

  • fileapi/BlobBuilder.h: Switch to using BlobData.
  • fileapi/BlobURL.cpp: Add a new helper method used in FormData.

(WebCore::BlobURL::getIdentifier):

  • fileapi/BlobURL.h:
  • fileapi/File.cpp: Switch to using BlobData.

(WebCore::createBlobDataForFile):
(WebCore::File::File):
(WebCore::File::size):
(WebCore::File::captureSnapshot):

  • fileapi/File.h: Switch to using BlobData.

(WebCore::File::create):
(WebCore::File::path):
(WebCore::File::name):
(WebCore::File::webkitRelativePath):

  • fileapi/FileReader.cpp: Change the reading to route through blob resource loading.

(WebCore::FileReader::FileReader):
(WebCore::FileReader::readAsBinaryString):
(WebCore::FileReader::readAsText):
(WebCore::FileReader::readAsDataURL):
(WebCore::delayedStart):
(WebCore::FileReader::readInternal):
(WebCore::FileReader::terminate):
(WebCore::FileReader::start):
(WebCore::FileReader::didReceiveResponse):
(WebCore::FileReader::didReceiveData):
(WebCore::FileReader::didFinishLoading):
(WebCore::FileReader::didFail):
(WebCore::FileReader::failed):
(WebCore::FileReader::httpStatusCodeToExceptionCode):
(WebCore::FileReader::result):
(WebCore::FileReader::convertToDataURL):

  • fileapi/FileReader.h:
  • html/FormDataList.cpp: Account to BlobData change.

(WebCore::FormDataList::appendString):
(WebCore::FormDataList::appendBlob):

  • html/FormDataList.h: Account to BlobData change.

(WebCore::FormDataList::appendBlob):
(WebCore::FormDataList::Item::Item):
(WebCore::FormDataList::Item::data):
(WebCore::FormDataList::Item::blob):
(WebCore::FormDataList::items):

  • loader/FormSubmission.cpp: Account to BlobData change.

(WebCore::FormSubmission::create):

  • platform/BlobItem.cpp: Removed.
  • platform/BlobItem.h: Removed.
  • platform/network/BlobRegistryImpl.cpp: Add the implementations for resource loading.

(WebCore::BlobRegistryImpl::createResourceHandle):
(WebCore::BlobRegistryImpl::loadResourceSynchronously):

  • platform/network/BlobResourceHandle.cpp: Fix a bug that the ref is not added.

(WebCore::BlobResourceHandle::BlobResourceHandle):

  • platform/network/FormData.cpp: Account to BlobData change.

(WebCore::FormData::create):
(WebCore::FormData::createMultiPart):
(WebCore::FormData::deepCopy):
(WebCore::FormData::appendFile):
(WebCore::FormData::appendKeyValuePairItems):

  • platform/network/FormData.h: Account to BlobData change.
  • platform/network/mac/FormDataStreamMac.mm: Resolve blob references in the form data.

(WebCore::closeCurrentStream):
(WebCore::advanceCurrentStream):
(WebCore::formCreate):
(WebCore::formRead):
(WebCore::setHTTPBody):

  • xml/XMLHttpRequest.cpp: Account to BlobData change.

(WebCore::XMLHttpRequest::send):

WebKit/chromium:

  • src/WebSearchableFormData.cpp:

(WebCore::HasSuitableTextElement):

LayoutTests:

Add a new test and change an existing test. Both tests are written in
better organized utility files and modules.

  • fast/files/file-reader-expected.txt: Removed.
  • fast/files/file-reader.html: Removed.
  • fast/files/read-blob-async-expected.txt: Added.
  • fast/files/read-blob-async.html: Added.
  • fast/files/read-file-async-expected.txt: Added.
  • fast/files/read-file-async.html: Added.
  • fast/files/resources/UTF8-2.txt: Added.
  • fast/files/resources/UTF8-3.txt: Added.
  • fast/files/resources/read-blob-test-cases.js: Added.
  • fast/files/resources/read-common.js: Added.
  • fast/files/resources/read-file-test-cases.js: Added.
  • fast/files/resources/setup-for-read-common.js: Added.
  • platform/gtk/Skipped: Account to the test changes for gtk.
  • platform/mac-wk2/Skipped: Account to the test changes for mac-wk2.
  • platform/qt/Skipped: Account to the test changes for qt.
  • platform/win/Skipped: Account to the test changes for win.
Location:
trunk
Files:
8 added
3 deleted
33 edited
1 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r66449 r66452  
     12010-08-30  Jian Li  <jianli@chromium.org>
     2
     3        Reviewed by Darin Fisher.
     4
     5        Switch the Blob implementation to using the blob data registration model
     6        https://bugs.webkit.org/show_bug.cgi?id=44389
     7
     8        Add a new test and change an existing test. Both tests are written in
     9        better organized utility files and modules.
     10
     11        * fast/files/file-reader-expected.txt: Removed.
     12        * fast/files/file-reader.html: Removed.
     13        * fast/files/read-blob-async-expected.txt: Added.
     14        * fast/files/read-blob-async.html: Added.
     15        * fast/files/read-file-async-expected.txt: Added.
     16        * fast/files/read-file-async.html: Added.
     17        * fast/files/resources/UTF8-2.txt: Added.
     18        * fast/files/resources/UTF8-3.txt: Added.
     19        * fast/files/resources/read-blob-test-cases.js: Added.
     20        * fast/files/resources/read-common.js: Added.
     21        * fast/files/resources/read-file-test-cases.js: Added.
     22        * fast/files/resources/setup-for-read-common.js: Added.
     23        * platform/gtk/Skipped: Account to the test changes for gtk.
     24        * platform/mac-wk2/Skipped: Account to the test changes for mac-wk2.
     25        * platform/qt/Skipped: Account to the test changes for qt.
     26        * platform/win/Skipped: Account to the test changes for win.
     27
    1282010-08-30  Eric Seidel  <eric@webkit.org>
    229
  • trunk/LayoutTests/fast/files/read-blob-async-expected.txt

    r66450 r66452  
    11
    2 Test reading a non-existent file
     2Test reading a blob containing non-existent file
    33readyState: 0
    44Received error event
     
    66error code: 8
    77Received loadend event
    8 Test reading an empty file as binary string
     8Test reading a blob containing existent and non-existent file
     9readyState: 0
     10Received error event
     11readyState: 2
     12error code: 8
     13Received loadend event
     14Test reading a blob containing empty file
    915readyState: 0
    1016Received loadstart event
     
    1521result:
    1622Received loadend event
    17 Test reading an empty file as text
     23Test reading a blob containing empty text
    1824readyState: 0
    1925Received loadstart event
     
    2430result:
    2531Received loadend event
    26 Test reading an empty file as data URL
     32Test reading a blob containing empty files and empty texts
    2733readyState: 0
    2834Received loadstart event
     
    3036Received load event
    3137readyState: 2
    32 result size: 5
    33 result: data:
     38result size: 0
     39result:
    3440Received loadend event
    35 Test reading a UTF-8 file as binary string
     41Test reading a blob containing single file
    3642readyState: 0
    3743Received loadstart event
     
    4248result: Hello
    4349Received loadend event
    44 Test reading a binary file as binary string
    45 readyState: 0
    46 Received loadstart event
    47 readyState: 1
    48 Received load event
    49 readyState: 2
    50 result size: 9
    51 result: 0x0 0x1 0x2 0x80 0x81 0x82 0xfd 0xfe 0xff
    52 Received loadend event
    53 Test reading a UTF-8 file as text
     50Test reading a blob containing single text
    5451readyState: 0
    5552Received loadstart event
     
    5855readyState: 2
    5956result size: 5
    60 result: Hello
     57result: First
    6158Received loadend event
    62 Test reading a UTF-16BE BOM file as text
     59Test reading a blob containing sliced file
    6360readyState: 0
    6461Received loadstart event
     
    6764readyState: 2
    6865result size: 5
    69 result: Hello
     66result: onder
    7067Received loadend event
    71 Test reading a UTF-16LE BOM file as text
     68Test reading a blob containing sliced text
    7269readyState: 0
    7370Received loadstart event
     
    7572Received load event
    7673readyState: 2
    77 result size: 5
    78 result: Hello
     74result size: 4
     75result: irst
    7976Received loadend event
    80 Test reading a UTF-8 BOM file as text
     77Test reading a blob containing multiple files
    8178readyState: 0
    8279Received loadstart event
     
    8481Received load event
    8582readyState: 2
    86 result size: 5
    87 result: Hello
     83result size: 19
     84result: HelloWonderfulWorld
    8885Received loadend event
    89 Test reading a UTF-16BE file as text with UTF-16BE encoding
     86Test reading a blob containing multiple texts
    9087readyState: 0
    9188Received loadstart event
     
    9390Received load event
    9491readyState: 2
    95 result size: 5
    96 result: Hello
     92result size: 16
     93result: FirstSecondThird
    9794Received loadend event
    98 Test reading a UTF-16BE BOM file as text with UTF8 encoding
     95Test reading a hybrid blob
    9996readyState: 0
    10097Received loadstart event
     
    10299Received load event
    103100readyState: 2
    104 result size: 5
    105 result: Hello
     101result size: 35
     102result: FirstHelloSecondWonderfulWorldThird
    106103Received loadend event
    107 Test reading a UTF-16BE BOM file as text with invalid encoding
     104Test reading a sliced hybrid blob
    108105readyState: 0
    109106Received loadstart event
     
    111108Received load event
    112109readyState: 2
    113 result size: 5
    114 result: Hello
     110result size: 12
     111result: lloSecondWon
    115112Received loadend event
    116 Test reading a UTF-8 file as data URL
     113Test reading a triple-sliced hybrid blob
    117114readyState: 0
    118115Received loadstart event
     
    120117Received load event
    121118readyState: 2
    122 result size: 31
    123 result: data:text/plain;base64,SGVsbG8=
    124 Received loadend event
    125 Test calling multiple read methods and only last one is processed
    126 readyState: 0
    127 Received loadstart event
    128 readyState: 1
    129 Received load event
    130 readyState: 2
    131 result size: 31
    132 result: data:text/plain;base64,SGVsbG8=
     119result size: 30
     120result: ondWonderfulWorldThirdFooloSec
    133121Received loadend event
    134122DONE
  • trunk/LayoutTests/fast/files/read-file-async-expected.txt

    r66450 r66452  
    11
    2 Test reading a non-existent file
     2Test reading a non-existent file as binary string
     3readyState: 0
     4Received error event
     5readyState: 2
     6error code: 8
     7Received loadend event
     8Test reading a non-existent file as text
     9readyState: 0
     10Received error event
     11readyState: 2
     12error code: 8
     13Received loadend event
     14Test reading a non-existent file as data URL
    315readyState: 0
    416Received error event
  • trunk/LayoutTests/platform/gtk/Skipped

    r66400 r66452  
    31473147http/tests/local/formdata/send-form-data-with-sliced-file.html
    31483148http/tests/local/formdata/upload-events.html
    3149 fast/files/file-reader.html
     3149fast/files/read-blob-async.html
     3150fast/files/read-file-async.html
    31503151http/tests/media/video-play-stall-seek.html
    31513152http/tests/media/video-play-stall.html
  • trunk/LayoutTests/platform/mac-wk2/Skipped

    r66325 r66452  
    365365fast/events/window-events-capture.html
    366366fast/events/zoom-dblclick.html
    367 fast/files/file-reader.html
     367fast/files/read-blob-async.html
     368fast/files/read-file-async.html
    368369fast/forms/25153.html
    369370fast/forms/access-key.html
  • trunk/LayoutTests/platform/qt/Skipped

    r66408 r66452  
    782782# Missing eventSender.beginDragWithFiles()
    783783fast/dom/Window/window-postmessage-clone-frames.html
    784 fast/files/file-reader.html
     784fast/files/read-blob-async.html
     785fast/files/read-file-async.html
    785786
    786787# Missing layoutTestController.setAlwaysAcceptCookies()
  • trunk/LayoutTests/platform/win/Skipped

    r66392 r66452  
    196196fast/events/drag-file-crash.html
    197197fast/dom/Window/window-postmessage-clone.html
    198 fast/files/file-reader.html
     198fast/files/read-blob-async.html
     199fast/files/read-file-async.html
    199200
    200201# Need to add functionality to DumpRenderTree to test IDN <rdar://problem/5301954>
  • trunk/WebCore/CMakeLists.txt

    r66417 r66452  
    12201220    platform/Arena.cpp
    12211221    platform/AsyncFileSystem.cpp
    1222     platform/BlobItem.cpp
    12231222    platform/ContentType.cpp
    12241223    platform/ContextMenu.cpp
  • trunk/WebCore/ChangeLog

    r66449 r66452  
     12010-08-30  Jian Li  <jianli@chromium.org>
     2
     3        Reviewed by Darin Fisher.
     4
     5        Switch the Blob implementation to using the blob data registration model
     6        https://bugs.webkit.org/show_bug.cgi?id=44389
     7
     8        Tests: fast/files/read-blob-async.html
     9               fast/files/read-file-async.html
     10
     11        With this switch, File/Blob/BlobBuilder are changed to register the blob
     12        data. FileReader is changed to route through loading the blob resource.
     13        FormData is also updated to take BlobData. The WebKit mac implementation
     14        is updated to resolve the blob references in the BlobData.
     15
     16        * CMakeLists.txt: Update the project file to remove BlobItem.*.
     17        * GNUmakefile.am: Update the project file to remove BlobItem.*.
     18        * WebCore.gypi: Update the project file to remove BlobItem.*.
     19        * WebCore.pro: Update the project file to remove BlobItem.*.
     20        * WebCore.vcproj/WebCore.vcproj: Update the project file to remove BlobItem.*.
     21        * WebCore.xcodeproj/project.pbxproj: Update the project file to remove BlobItem.*.
     22        * fileapi/Blob.cpp: Switch to using BlobData.
     23        (WebCore::Blob::Blob):
     24        (WebCore::Blob::slice):
     25        * fileapi/Blob.h: Switch to using BlobData.
     26        (WebCore::Blob::create):
     27        (WebCore::Blob::size):
     28        (WebCore::Blob::isFile):
     29        * fileapi/BlobBuilder.cpp: Switch to using BlobData.
     30        (WebCore::BlobBuilder::BlobBuilder):
     31        (WebCore::BlobBuilder::append):
     32        (WebCore::BlobBuilder::getBlob):
     33        * fileapi/BlobBuilder.h: Switch to using BlobData.
     34        * fileapi/BlobURL.cpp: Add a new helper method used in FormData.
     35        (WebCore::BlobURL::getIdentifier):
     36        * fileapi/BlobURL.h:
     37        * fileapi/File.cpp: Switch to using BlobData.
     38        (WebCore::createBlobDataForFile):
     39        (WebCore::File::File):
     40        (WebCore::File::size):
     41        (WebCore::File::captureSnapshot):
     42        * fileapi/File.h: Switch to using BlobData.
     43        (WebCore::File::create):
     44        (WebCore::File::path):
     45        (WebCore::File::name):
     46        (WebCore::File::webkitRelativePath):
     47        * fileapi/FileReader.cpp: Change the reading to route through blob resource loading.
     48        (WebCore::FileReader::FileReader):
     49        (WebCore::FileReader::readAsBinaryString):
     50        (WebCore::FileReader::readAsText):
     51        (WebCore::FileReader::readAsDataURL):
     52        (WebCore::delayedStart):
     53        (WebCore::FileReader::readInternal):
     54        (WebCore::FileReader::terminate):
     55        (WebCore::FileReader::start):
     56        (WebCore::FileReader::didReceiveResponse):
     57        (WebCore::FileReader::didReceiveData):
     58        (WebCore::FileReader::didFinishLoading):
     59        (WebCore::FileReader::didFail):
     60        (WebCore::FileReader::failed):
     61        (WebCore::FileReader::httpStatusCodeToExceptionCode):
     62        (WebCore::FileReader::result):
     63        (WebCore::FileReader::convertToDataURL):
     64        * fileapi/FileReader.h:
     65        * html/FormDataList.cpp: Account to BlobData change.
     66        (WebCore::FormDataList::appendString):
     67        (WebCore::FormDataList::appendBlob):
     68        * html/FormDataList.h: Account to BlobData change.
     69        (WebCore::FormDataList::appendBlob):
     70        (WebCore::FormDataList::Item::Item):
     71        (WebCore::FormDataList::Item::data):
     72        (WebCore::FormDataList::Item::blob):
     73        (WebCore::FormDataList::items):
     74        * loader/FormSubmission.cpp: Account to BlobData change.
     75        (WebCore::FormSubmission::create):
     76        * platform/BlobItem.cpp: Removed.
     77        * platform/BlobItem.h: Removed.
     78        * platform/network/BlobRegistryImpl.cpp: Add the implementations for resource loading.
     79        (WebCore::BlobRegistryImpl::createResourceHandle):
     80        (WebCore::BlobRegistryImpl::loadResourceSynchronously):
     81        * platform/network/BlobResourceHandle.cpp: Fix a bug that the ref is not added.
     82        (WebCore::BlobResourceHandle::BlobResourceHandle):
     83        * platform/network/FormData.cpp: Account to BlobData change.
     84        (WebCore::FormData::create):
     85        (WebCore::FormData::createMultiPart):
     86        (WebCore::FormData::deepCopy):
     87        (WebCore::FormData::appendFile):
     88        (WebCore::FormData::appendKeyValuePairItems):
     89        * platform/network/FormData.h: Account to BlobData change.
     90        * platform/network/mac/FormDataStreamMac.mm: Resolve blob references in the form data.
     91        (WebCore::closeCurrentStream):
     92        (WebCore::advanceCurrentStream):
     93        (WebCore::formCreate):
     94        (WebCore::formRead):
     95        (WebCore::setHTTPBody):
     96        * xml/XMLHttpRequest.cpp: Account to BlobData change.
     97        (WebCore::XMLHttpRequest::send):
     98
    1992010-08-30  Eric Seidel  <eric@webkit.org>
    2100
  • trunk/WebCore/GNUmakefile.am

    r66398 r66452  
    18791879        WebCore/platform/AsyncFileStream.h \
    18801880        WebCore/platform/AutodrainedPool.h \
    1881         WebCore/platform/BlobItem.cpp \
    1882         WebCore/platform/BlobItem.h \
    18831881        WebCore/platform/ContentType.cpp \
    18841882        WebCore/platform/ContentType.h \
  • trunk/WebCore/WebCore.gypi

    r66369 r66452  
    30553055            'platform/AsyncFileSystemCallbacks.h',
    30563056            'platform/AutodrainedPool.h',
    3057             'platform/BlobItem.cpp',
    3058             'platform/BlobItem.h',
    30593057            'platform/ContentType.cpp',
    30603058            'platform/ContentType.h',
  • trunk/WebCore/WebCore.pro

    r66384 r66452  
    878878    platform/Arena.cpp \
    879879    platform/AsyncFileSystem.cpp \
    880     platform/BlobItem.cpp \
    881880    platform/text/Base64.cpp \
    882881    platform/text/BidiContext.cpp \
     
    16831682    platform/AsyncFileSystem.h \
    16841683    platform/AsyncFileSystemCallbacks.h \
    1685     platform/BlobItem.h \
    16861684    platform/ContentType.h \
    16871685    platform/ContextMenu.h \
  • trunk/WebCore/WebCore.vcproj/WebCore.vcproj

    r66365 r66452  
    2399823998                        </File>
    2399923999                        <File
    24000                                 RelativePath="..\platform\BlobItem.cpp"
    24001                                 >
    24002                         </File>
    24003                         <File
    24004                                 RelativePath="..\platform\BlobItem.h"
    24005                                 >
    24006                         </File>
    24007                         <File
    2400824000                                RelativePath="..\platform\ContentType.cpp"
    2400924001                                >
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r66365 r66452  
    23892389                898783D312232A13003AABDA /* LocalFileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 898783D112232A13003AABDA /* LocalFileSystem.cpp */; };
    23902390                898783D412232A13003AABDA /* LocalFileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 898783D212232A13003AABDA /* LocalFileSystem.h */; };
    2391                 8988E10E11A3508B00DB732E /* BlobItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8988E10C11A3508B00DB732E /* BlobItem.cpp */; };
    2392                 8988E10F11A3508B00DB732E /* BlobItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 8988E10D11A3508B00DB732E /* BlobItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
    23932391                899ABC261215E4A300F9F219 /* DirectoryEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 899ABC201215E4A300F9F219 /* DirectoryEntry.cpp */; };
    23942392                899ABC271215E4A300F9F219 /* DirectoryEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 899ABC211215E4A300F9F219 /* DirectoryEntry.h */; };
     
    82908288                898783D112232A13003AABDA /* LocalFileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LocalFileSystem.cpp; sourceTree = "<group>"; };
    82918289                898783D212232A13003AABDA /* LocalFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalFileSystem.h; sourceTree = "<group>"; };
    8292                 8988E10C11A3508B00DB732E /* BlobItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlobItem.cpp; sourceTree = "<group>"; };
    8293                 8988E10D11A3508B00DB732E /* BlobItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobItem.h; sourceTree = "<group>"; };
    82948290                899ABC201215E4A300F9F219 /* DirectoryEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryEntry.cpp; sourceTree = "<group>"; };
    82958291                899ABC211215E4A300F9F219 /* DirectoryEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryEntry.h; sourceTree = "<group>"; };
     
    1665716653                                89D08D9E12228451001241DF /* AsyncFileSystemCallbacks.h */,
    1665816654                                51E1ECB10C91C55600DC255B /* AutodrainedPool.h */,
    16659                                 8988E10C11A3508B00DB732E /* BlobItem.cpp */,
    16660                                 8988E10D11A3508B00DB732E /* BlobItem.h */,
    1666116655                                BCC8CFCA0986CD2400140BF2 /* ColorData.gperf */,
    1666216656                                41D015C90F4B5C71004A662F /* ContentType.cpp */,
     
    1777217766                                938192050F87E1EC00D5352A /* BinaryPropertyList.h in Headers */,
    1777317767                                A89943280B42338800D7C802 /* BitmapImage.h in Headers */,
    17774                                 8988E10F11A3508B00DB732E /* BlobItem.h in Headers */,
    1777517768                                93F199BE08245E59001E9ABC /* BlockExceptions.h in Headers */,
    1777617769                                BC5EB5E10E81BE8700B25965 /* BorderData.h in Headers */,
     
    2079620789                                938192030F87E1E600D5352A /* BinaryPropertyList.cpp in Sources */,
    2079720790                                A89943290B42338800D7C802 /* BitmapImage.cpp in Sources */,
    20798                                 8988E10E11A3508B00DB732E /* BlobItem.cpp in Sources */,
    2079920791                                93F19AE108245E59001E9ABC /* BlockExceptions.mm in Sources */,
    2080020792                                BCEA4854097D93020094C9E4 /* break_lines.cpp in Sources */,
  • trunk/WebCore/fileapi/Blob.cpp

    r66365 r66452  
    3232#include "Blob.h"
    3333
    34 #include "BlobData.h"
    35 #include "BlobItem.h"
    3634#include "BlobURL.h"
    37 #include "FileSystem.h"
     35#include "File.h"
    3836#include "ScriptExecutionContext.h"
    3937#include "ThreadableBlobRegistry.h"
    4038
    4139namespace WebCore {
    42 
    43 // FIXME: To be removed when we switch to using BlobData.
    44 Blob::Blob(ScriptExecutionContext* scriptExecutionContext, const String& type, const BlobItemList& items)
    45     : m_scriptExecutionContext(scriptExecutionContext)
    46     , m_type(type)
    47     , m_size(0)
    48 {
    49     m_scriptExecutionContext->addBlob(this);
    50     for (size_t i = 0; i < items.size(); ++i)
    51         m_items.append(items[i]);
    52 }
    53 
    54 // FIXME: To be removed when we switch to using BlobData.
    55 Blob::Blob(ScriptExecutionContext* scriptExecutionContext, const PassRefPtr<BlobItem>& item)
    56     : m_scriptExecutionContext(scriptExecutionContext)
    57     , m_size(0)
    58 {
    59     m_scriptExecutionContext->addBlob(this);
    60     m_items.append(item);
    61 }
    62 
    63 // FIXME: To be removed when we switch to using BlobData.
    64 Blob::Blob(ScriptExecutionContext* scriptExecutionContext, const String& path)
    65     : m_scriptExecutionContext(scriptExecutionContext)
    66     , m_size(0)
    67 {
    68     m_scriptExecutionContext->addBlob(this);
    69     // Note: this doesn't initialize the type unlike File(path).
    70     m_items.append(FileBlobItem::create(path));
    71 }
    7240
    7341Blob::Blob(ScriptExecutionContext* scriptExecutionContext, PassOwnPtr<BlobData> blobData, long long size)
     
    7644    , m_size(size)
    7745{
    78     ASSERT(blobData.get() && !blobData->items().isEmpty());
     46    ASSERT(blobData);
    7947
    8048    m_scriptExecutionContext->addBlob(this);
     
    9058    , m_size(size)
    9159{
    92     m_scriptExecutionContext->addBlob(this);
    93 
    94     // FIXME: To be removed when we switch to using BlobData.
    95     if (srcURL.isEmpty())
    96         return;
     60   m_scriptExecutionContext->addBlob(this);
    9761
    9862    // Create a new internal URL and register it with the same blob data as the source URL.
     
    11983}
    12084
    121 unsigned long long Blob::size() const
    122 {
    123     // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
    124     // come up with an exception to throw if file size is not represetable.
    125     unsigned long long size = 0;
    126     for (size_t i = 0; i < m_items.size(); ++i)
    127         size += m_items[i]->size();
    128     return size;
    129 }
    130 
    131 // FIXME: To be removed when we switch to using BlobData.
    132 const String& Blob::path() const
    133 {
    134     ASSERT(m_items.size() == 1 && m_items[0]->toFileBlobItem());
    135     return m_items[0]->toFileBlobItem()->path();
    136 }
    137 
    13885#if ENABLE(BLOB)
    13986PassRefPtr<Blob> Blob::slice(ScriptExecutionContext* scriptExecutionContext, long long start, long long length, const String& contentType) const
    14087{
     88    // When we slice a file for the first time, we obtain a snapshot of the file by capturing its current size and modification time.
     89    // The modification time will be used to verify if the file has been changed or not, when the underlying data are accessed.
     90    long long size;
     91    double modificationTime;
     92    if (isFile())
     93        // FIXME: This involves synchronous file operation. We need to figure out how to make it asynchronous.
     94        static_cast<const File*>(this)->captureSnapshot(size, modificationTime);
     95    else {
     96        ASSERT(m_size != -1);
     97        size = m_size;
     98    }
     99
     100    // Clamp the range if it exceeds the size limit.
    141101    if (start < 0)
    142102        start = 0;
     
    144104        length = 0;
    145105
    146     // Clamp the range if it exceeds the size limit.
    147     unsigned long long totalSize = size();
    148     if (static_cast<unsigned long long>(start) > totalSize) {
     106    if (start >= size) {
    149107        start = 0;
    150108        length = 0;
    151     } else if (static_cast<unsigned long long>(start + length) > totalSize)
    152         length = totalSize - start;
     109    } else if (start + length > size)
     110        length = size - start;
    153111
    154     size_t i = 0;
    155     BlobItemList items;
    156     for (; i < m_items.size() && static_cast<unsigned long long>(start) >= m_items[i]->size(); ++i)
    157         start -= m_items[i]->size();
    158     for (; length > 0 && i < m_items.size(); ++i) {
    159         items.append(m_items[i]->slice(start, length));
    160         length -= items.last()->size();
    161         start = 0;
    162     }
    163     return Blob::create(scriptExecutionContext, contentType, items);
     112    OwnPtr<BlobData> blobData = BlobData::create();
     113    blobData->setContentType(contentType);
     114    if (isFile())
     115        blobData->appendFile(static_cast<const File*>(this)->path(), start, length, modificationTime);
     116    else
     117        blobData->appendBlob(m_url, start, length);
     118
     119    return Blob::create(scriptExecutionContext, blobData.release(), length);
    164120}
    165 #endif // ENABLE(BLOB)
     121#endif
    166122
    167123} // namespace WebCore
  • trunk/WebCore/fileapi/Blob.h

    r66365 r66452  
    3232#define Blob_h
    3333
    34 #include "BlobItem.h"
     34#include "BlobData.h"
    3535#include "KURL.h"
    3636#include "PlatformString.h"
     
    4242namespace WebCore {
    4343
    44 class BlobData;
    4544class ScriptExecutionContext;
    4645
    4746class Blob : public RefCounted<Blob> {
    4847public:
    49     // FIXME: To be removed when we switch to using BlobData.
    50     static PassRefPtr<Blob> create(ScriptExecutionContext* scriptExecutionContext, const String& type, const BlobItemList& items)
     48    static PassRefPtr<Blob> create(ScriptExecutionContext* scriptExecutionContext, PassOwnPtr<BlobData> blobData, long long size)
    5149    {
    52         return adoptRef(new Blob(scriptExecutionContext, type, items));
     50        return adoptRef(new Blob(scriptExecutionContext, blobData, size));
    5351    }
    5452
     
    6462
    6563    const KURL& url() const { return m_url; }
    66     unsigned long long size() const;
    6764    const String& type() const { return m_type; }
     65
     66    virtual unsigned long long size() const { return static_cast<unsigned long long>(m_size); }
    6867    virtual bool isFile() const { return false; }
    69 
    70     // FIXME: To be removed when we switch to using BlobData.
    71     const String& path() const;
    72 
    73     // FIXME: To be removed when we switch to using BlobData.
    74     const BlobItemList& items() const { return m_items; }
    7568
    7669#if ENABLE(BLOB)
     
    7972
    8073protected:
    81     // FIXME: To be removed when we switch to using BlobData.
    82     Blob(ScriptExecutionContext*, const String& type, const BlobItemList&);
    83     Blob(ScriptExecutionContext*, const PassRefPtr<BlobItem>&);
    84     Blob(ScriptExecutionContext*, const String& path);
    85 
    8674    Blob(ScriptExecutionContext*, PassOwnPtr<BlobData>, long long size);
    8775
     
    8977    Blob(ScriptExecutionContext*, const KURL& srcURL, const String& type, long long size);
    9078
    91     // FIXME: To be removed when we switch to using BlobData.
    92     BlobItemList m_items;
    93 
    9479    // This is an internal URL referring to the blob data associated with this object.
    9580    // It is only used by FileReader to read the blob data via loading from the blob URL resource.
    9681    KURL m_url;
    97 
     82   
    9883    ScriptExecutionContext* m_scriptExecutionContext;
    9984    String m_type;
  • trunk/WebCore/fileapi/BlobBuilder.cpp

    r66365 r66452  
    3535#include "Blob.h"
    3636#include "ExceptionCode.h"
     37#include "File.h"
    3738#include "LineEnding.h"
    3839#include "TextEncoding.h"
     
    5758}
    5859
     60BlobBuilder::BlobBuilder()
     61    : m_size(0)
     62{
     63}
     64
    5965bool BlobBuilder::append(const String& text, const String& endingType, ExceptionCode& ec)
    6066{
     
    6369        return false;
    6470
    65     m_items.append(StringBlobItem::create(cstr));
     71    m_size += cstr.length();
     72    m_items.append(BlobDataItem(cstr));
    6673    return true;
    6774}
     
    7481bool BlobBuilder::append(PassRefPtr<Blob> blob)
    7582{
    76     if (blob) {
    77         for (size_t i = 0; i < blob->items().size(); ++i)
    78             m_items.append(blob->items()[i]);
    79         return true;
     83    if (blob->isFile()) {
     84        // If the blob is file that is not snapshoted, capture the snapshot now.
     85        // FIXME: This involves synchronous file operation. We need to figure out how to make it asynchronous.
     86        File* file = static_cast<File*>(blob.get());
     87        long long snapshotSize;
     88        double snapshotModificationTime;
     89        file->captureSnapshot(snapshotSize, snapshotModificationTime);
     90
     91        m_size += snapshotSize;
     92        m_items.append(BlobDataItem(file->path(), 0, snapshotSize, snapshotModificationTime));
     93    } else {
     94        long long blobSize = static_cast<long long>(blob->size());
     95        m_size += blobSize;
     96        m_items.append(BlobDataItem(blob->url(), 0, blobSize));
    8097    }
    81     return false;
     98    return true;
    8299}
    83100
    84 PassRefPtr<Blob> BlobBuilder::getBlob(ScriptExecutionContext* scriptExecutionContext, const String& contentType) const
     101PassRefPtr<Blob> BlobBuilder::getBlob(ScriptExecutionContext* scriptExecutionContext, const String& contentType)
    85102{
    86     return Blob::create(scriptExecutionContext, contentType, m_items);
     103    OwnPtr<BlobData> blobData = BlobData::create();
     104    blobData->setContentType(contentType);
     105    blobData->swapItems(m_items);
     106
     107    RefPtr<Blob> blob = Blob::create(scriptExecutionContext, blobData.release(), m_size);
     108
     109    // After creating a blob from the current blob data, we do not need to keep the data around any more. Instead, we only
     110    // need to keep a reference to the URL of the blob just created.
     111    m_items.append(BlobDataItem(blob->url(), 0, m_size));
     112
     113    return blob;
    87114}
    88115
  • trunk/WebCore/fileapi/BlobBuilder.h

    r66365 r66452  
    3232#define BlobBuilder_h
    3333
    34 #include "BlobItem.h"
     34#include "BlobData.h"
     35#include "PlatformString.h"
    3536#include <wtf/PassRefPtr.h>
    3637#include <wtf/RefCounted.h>
     38#include <wtf/Vector.h>
     39#include <wtf/text/CString.h>
    3740
    3841namespace WebCore {
     
    4043class Blob;
    4144class ScriptExecutionContext;
     45class TextEncoding;
    4246
    4347typedef int ExceptionCode;
     
    5155    bool append(const String& text, const String& ending, ExceptionCode&);
    5256
    53     PassRefPtr<Blob> getBlob(ScriptExecutionContext*, const String& contentType = String()) const;
     57    PassRefPtr<Blob> getBlob(ScriptExecutionContext*, const String& contentType = String());
    5458
    5559private:
    56     BlobItemList m_items;
     60    BlobBuilder();
     61
     62    long long m_size;
     63    BlobDataItemList m_items;
    5764};
    5865
  • trunk/WebCore/fileapi/BlobURL.cpp

    r66365 r66452  
    6464}
    6565
     66String BlobURL::getIdentifier(const KURL& url)
     67{
     68    ASSERT(url.protocolIs("blob"));
     69
     70    unsigned startIndex = url.pathAfterLastSlash();
     71    return url.string().substring(startIndex);
     72}
     73
    6674} // namespace WebCore
  • trunk/WebCore/fileapi/BlobURL.h

    r66365 r66452  
    4242    static KURL createURL(ScriptExecutionContext*);
    4343    static KURL getOrigin(const KURL&);
     44    static String getIdentifier(const KURL& url);
    4445};
    4546
  • trunk/WebCore/fileapi/File.cpp

    r66365 r66452  
    2727#include "File.h"
    2828
    29 #include "BlobData.h"
     29#include "BlobRegistry.h"
    3030#include "FileSystem.h"
    3131#include "MIMETypeRegistry.h"
     
    3333namespace WebCore {
    3434
     35static PassOwnPtr<BlobData> createBlobDataForFile(const String& path)
     36{
     37    String type;
     38    int index = path.reverseFind('.');
     39    if (index != -1)
     40        type = MIMETypeRegistry::getMIMETypeForExtension(path.substring(index + 1));
     41
     42    OwnPtr<BlobData> blobData = BlobData::create();
     43    blobData->setContentType(type);
     44    blobData->appendFile(path);
     45    return blobData.release();
     46}
     47
    3548File::File(ScriptExecutionContext* scriptExecutionContext, const String& path)
    36     : Blob(scriptExecutionContext, path)
     49    : Blob(scriptExecutionContext, createBlobDataForFile(path), -1)
     50    , m_path(path)
     51    , m_name(pathGetFileName(path))
    3752{
    38     Init();
    3953}
    4054
    4155File::File(ScriptExecutionContext* scriptExecutionContext, const String& path, const KURL& url, const String& type)
    42     : Blob(scriptExecutionContext, url, type, BlobDataItem::toEndOfFile)
     56    : Blob(scriptExecutionContext, url, type, -1)
     57    , m_path(path)
    4358{
    44     // FIXME: To be removed when we switch to using BlobData.
    45      m_items.append(FileBlobItem::create(path));
     59    m_name = pathGetFileName(path);
    4660}
    4761
    4862#if ENABLE(DIRECTORY_UPLOAD)
    49 File::File(ScriptExecutionContext* scriptExecutionContext, const String& relativePath, const String& filePath)
    50     : Blob(scriptExecutionContext, FileBlobItem::create(filePath, relativePath))
     63File::File(ScriptExecutionContext* scriptExecutionContext, const String& relativePath, const String& path)
     64    : Blob(scriptExecutionContext, createBlobDataForFile(path), -1)
     65    , m_path(path)
     66    , m_relativePath(relativePath)
    5167{
    52     Init();
    5368}
    5469#endif
    5570
    56 void File::Init()
     71unsigned long long File::size() const
    5772{
    58     // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure.
    59     const String& fileName = name();
    60     size_t index = fileName.reverseFind('.');
    61     if (index != notFound)
    62         m_type = MIMETypeRegistry::getMIMETypeForExtension(fileName.substring(index + 1));
     73    // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
     74    // come up with an exception to throw if file size is not representable.
     75    long long size;
     76    if (!getFileSize(m_path, size))
     77        return 0;
     78    return static_cast<unsigned long long>(size);
    6379}
    6480
    65 const String& File::name() const
     81void File::captureSnapshot(long long& snapshotSize, double& snapshotModificationTime) const
    6682{
    67     return items().at(0)->toFileBlobItem()->name();
     83    // Obtains a snapshot of the file by capturing its current size and modification time. This is used when we slice a file for the first time.
     84    // If we fail to retrieve the size or modification time, probably due to that the file has been deleted, 0 size is returned.
     85    // FIXME: Combine getFileSize and getFileModificationTime into one file system call.
     86    time_t modificationTime;
     87    if (!getFileSize(m_path, snapshotSize) || !getFileModificationTime(m_path, modificationTime)) {
     88        snapshotSize = 0;
     89        snapshotModificationTime = 0;
     90    } else
     91        snapshotModificationTime = modificationTime;
    6892}
    6993
    70 #if ENABLE(DIRECTORY_UPLOAD)
    71 const String& File::webkitRelativePath() const
    72 {
    73     return items().at(0)->toFileBlobItem()->relativePath();
    74 }
    75 #endif
    76 
    7794} // namespace WebCore
  • trunk/WebCore/fileapi/File.h

    r66365 r66452  
    2828
    2929#include "Blob.h"
     30#include "PlatformString.h"
    3031#include <wtf/PassRefPtr.h>
    3132#include <wtf/RefCounted.h>
    3233
    3334namespace WebCore {
     35
     36class KURL;
     37class ScriptExecutionContext;
    3438
    3539class File : public Blob {
     
    4145
    4246    // For deserialization.
    43     static PassRefPtr<File> create(ScriptExecutionContext* scriptExecutionContext, const String& path, const KURL& url, const String& type)
     47    static PassRefPtr<File> create(ScriptExecutionContext* scriptExecutionContext, const String& path, const KURL& srcURL, const String& type)
    4448    {
    45         return adoptRef(new File(scriptExecutionContext, path, url, type));
     49        return adoptRef(new File(scriptExecutionContext, path, srcURL, type));
    4650    }
    4751
     
    5357#endif
    5458
     59    virtual unsigned long long size() const;
    5560    virtual bool isFile() const { return true; }
    5661
    57     const String& name() const;
     62    const String& path() const { return m_path; }
     63    const String& name() const { return m_name; }
    5864#if ENABLE(DIRECTORY_UPLOAD)
    5965    // Returns the relative path of this file in the context of a directory selection.
    60     const String& webkitRelativePath() const;
     66    const String& webkitRelativePath() const { return m_relativePath; }
    6167#endif
     68
     69    // Note that this involves synchronous file operation. Think twice before calling this function.
     70    void captureSnapshot(long long& snapshotSize, double& snapshotModificationTime) const;
    6271
    6372    // FIXME: obsolete attributes. To be removed.
     
    6776private:
    6877    File(ScriptExecutionContext*, const String& path);
    69 
     78   
    7079    // For deserialization.
    71     File(ScriptExecutionContext*, const String& path, const KURL&, const String& type);
     80    File(ScriptExecutionContext*, const String& path, const KURL& srcURL, const String& type);
    7281
    7382#if ENABLE(DIRECTORY_UPLOAD)
     
    7584#endif
    7685
    77     void Init();
     86    String m_path;
     87    String m_name;
     88#if ENABLE(DIRECTORY_UPLOAD)
     89    String m_relativePath;
     90#endif
    7891};
    7992
  • trunk/WebCore/fileapi/FileReader.cpp

    r66365 r66452  
    3737#include "Base64.h"
    3838#include "Blob.h"
     39#include "CrossThreadTask.h"
    3940#include "File.h"
    40 #include "FileStreamProxy.h"
    4141#include "Logging.h"
    4242#include "ProgressEvent.h"
     43#include "ResourceError.h"
     44#include "ResourceRequest.h"
    4345#include "ScriptExecutionContext.h"
    4446#include "TextResourceDecoder.h"
     47#include "ThreadableLoader.h"
    4548#include <wtf/CurrentTime.h>
    4649
    4750namespace WebCore {
    4851
    49 const unsigned bufferSize = 1024;
    5052const double progressNotificationIntervalMS = 50;
    5153
     
    6062    , m_lastProgressNotificationTimeMS(0)
    6163{
    62     m_buffer.resize(bufferSize);
    6364}
    6465
     
    8485}
    8586
    86 void FileReader::readAsBinaryString(Blob* fileBlob)
    87 {
    88     if (!fileBlob)
    89         return;
    90 
    91     // FIXME: needs to handle non-file blobs.
    92     LOG(FileAPI, "FileReader: reading as binary: %s\n", fileBlob->path().utf8().data());
    93 
    94     readInternal(fileBlob, ReadFileAsBinaryString);
    95 }
    96 
    97 void FileReader::readAsText(Blob* fileBlob, const String& encoding)
    98 {
    99     if (!fileBlob)
    100         return;
    101 
    102     // FIXME: needs to handle non-file blobs.
    103     LOG(FileAPI, "FileReader: reading as text: %s\n", fileBlob->path().utf8().data());
     87void FileReader::readAsBinaryString(Blob* blob)
     88{
     89    if (!blob)
     90        return;
     91
     92    LOG(FileAPI, "FileReader: reading as binary: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : "");
     93
     94    readInternal(blob, ReadFileAsBinaryString);
     95}
     96
     97void FileReader::readAsText(Blob* blob, const String& encoding)
     98{
     99    if (!blob)
     100        return;
     101
     102    LOG(FileAPI, "FileReader: reading as text: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : "");
    104103
    105104    if (!encoding.isEmpty())
    106105        m_encoding = TextEncoding(encoding);
    107     readInternal(fileBlob, ReadFileAsText);
    108 }
    109 
    110 void FileReader::readAsDataURL(File* file)
    111 {
    112     if (!file)
    113         return;
    114 
    115     LOG(FileAPI, "FileReader: reading as data URL: %s\n", file->path().utf8().data());
    116 
    117     m_fileType = file->type();
    118     readInternal(file, ReadFileAsDataURL);
    119 }
    120 
    121 void FileReader::readInternal(Blob* fileBlob, ReadType type)
     106    readInternal(blob, ReadFileAsText);
     107}
     108
     109void FileReader::readAsDataURL(Blob* blob)
     110{
     111    if (!blob)
     112        return;
     113
     114    LOG(FileAPI, "FileReader: reading as data URL: %s %s\n", blob->url().string().utf8().data(), blob->isFile() ? static_cast<File*>(blob)->path().utf8().data() : "");
     115
     116    m_fileType = blob->type();
     117    readInternal(blob, ReadFileAsDataURL);
     118}
     119
     120static void delayedStart(ScriptExecutionContext*, FileReader* reader)
     121{
     122    reader->start();
     123}
     124
     125void FileReader::readInternal(Blob* blob, ReadType type)
    122126{
    123127    // readAs*** methods() can be called multiple times. Only the last call before the actual reading happens is processed.
     
    125129        return;
    126130
    127     m_fileBlob = fileBlob;
     131    if (m_state == None)
     132        scriptExecutionContext()->postTask(createCallbackTask(&delayedStart, this));
     133
     134    m_blob = blob;
    128135    m_readType = type;
    129136    m_state = Starting;
    130 
    131     // When FileStreamProxy is created, FileReader::didStart() will get notified on the File thread and we will start
    132     // opening and reading the file since then.
    133     if (!m_streamProxy.get())
    134         m_streamProxy = FileStreamProxy::create(scriptExecutionContext(), this);
    135137}
    136138
     
    151153void FileReader::terminate()
    152154{
    153     if (m_streamProxy) {
    154         m_streamProxy->stop();
    155         m_streamProxy = 0;
     155    if (m_loader) {
     156        m_loader->cancel();
     157        m_loader = 0;
    156158    }
    157159    m_state = Completed;
    158160}
    159161
    160 void FileReader::didStart()
     162void FileReader::start()
    161163{
    162164    m_state = Opening;
    163165
    164     ASSERT(m_fileBlob->items().size() == 1 && m_fileBlob->items().at(0)->toFileBlobItem());
    165     const FileRangeBlobItem* fileRangeItem = m_fileBlob->items().at(0)->toFileRangeBlobItem();
    166     double expectedModificationTime = fileRangeItem ? fileRangeItem->snapshotModificationTime() : 0;
    167 
    168     m_streamProxy->getSize(m_fileBlob->path(), expectedModificationTime);
    169 }
    170 
    171 void FileReader::didGetSize(long long size)
    172 {
    173     // If the size is -1, it means the file has been moved or changed. Fail now.
    174     if (size == -1) {
    175         didFail(NOT_FOUND_ERR);
     166    // The blob is read by routing through the request handling layer given the blob url.
     167    ResourceRequest request(m_blob->url());
     168    request.setHTTPMethod("GET");
     169
     170    ThreadableLoaderOptions options;
     171    options.sendLoadCallbacks = true;
     172    options.sniffContent = false;
     173    options.forcePreflight = false;
     174    options.allowCredentials = true;
     175    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
     176
     177    m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options);
     178}
     179
     180void FileReader::didReceiveResponse(const ResourceResponse& response)
     181{
     182    if (response.httpStatusCode() != 200) {
     183        failed(response.httpStatusCode());
    176184        return;
    177185    }
     
    180188    fireEvent(eventNames().loadstartEvent);
    181189
    182     ASSERT(m_fileBlob->items().size() == 1 && m_fileBlob->items().at(0)->toFileBlobItem());
    183     const FileRangeBlobItem* fileRangeItem = m_fileBlob->items().at(0)->toFileRangeBlobItem();
    184     long long start = fileRangeItem ? fileRangeItem->start() : 0;
    185 
    186     // 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.
    187     m_totalBytes = fileRangeItem ? fileRangeItem->size() : size;
    188 
    189     m_streamProxy->openForRead(m_fileBlob->path(), start, m_totalBytes);
    190 }
    191 
    192 void FileReader::didOpen(bool success)
    193 {
    194     if (!success) {
    195         didFail(NOT_READABLE_ERR);
    196         return;
    197     }
    198    
    199     m_streamProxy->read(m_buffer.data(), m_buffer.size());
    200 }
    201 
    202 void FileReader::didRead(int bytesRead)
    203 {
     190    m_totalBytes = response.expectedContentLength();
     191}
     192
     193void FileReader::didReceiveData(const char* data, int lengthReceived)
     194{
     195    ASSERT(data && lengthReceived);
     196
    204197    // Bail out if we have aborted the reading.
    205198    if (m_state == Completed)
    206199        return;
    207200
    208     // If bytesRead is -1, it means an error happens.
    209     if (bytesRead == -1) {
    210         didFail(NOT_READABLE_ERR);
    211         return;
    212     }
    213 
    214     // If bytesRead is 0, it means the reading is done.
    215     if (!bytesRead) {
    216         didFinish();
    217         return;
    218     }
    219 
    220201    switch (m_readType) {
    221202    case ReadFileAsBinaryString:
    222         m_result += String(m_buffer.data(), static_cast<unsigned>(bytesRead));
     203        m_result += String(data, static_cast<unsigned>(lengthReceived));
    223204        break;
    224205    case ReadFileAsText:
    225206    case ReadFileAsDataURL:
    226         m_rawData.append(m_buffer.data(), static_cast<unsigned>(bytesRead));
     207        m_rawData.append(data, static_cast<unsigned>(lengthReceived));
    227208        m_isRawDataConverted = false;
    228209        break;
     
    231212    }
    232213
    233     m_bytesLoaded += bytesRead;
     214    m_bytesLoaded += lengthReceived;
    234215
    235216    // Fire the progress event at least every 50ms.
     
    241222        m_lastProgressNotificationTimeMS = now;
    242223    }
    243 
    244     // Continue reading.
    245     m_streamProxy->read(m_buffer.data(), m_buffer.size());
    246 }
    247 
    248 void FileReader::didFinish()
     224}
     225
     226void FileReader::didFinishLoading(unsigned long)
    249227{
    250228    m_state = Completed;
    251 
    252     m_streamProxy->close();
    253229
    254230    fireEvent(eventNames().loadEvent);
    255231    fireEvent(eventNames().loadendEvent);
    256 }
    257 
    258 void FileReader::didFail(ExceptionCode ec)
     232
     233    m_loader = 0;
     234}
     235
     236void FileReader::didFail(const ResourceError&)
     237{
     238    // Treat as internal error.
     239    failed(500);
     240}
     241
     242void FileReader::failed(int httpStatusCode)
    259243{
    260244    m_state = Completed;
    261     m_error = FileError::create(ec);
    262 
    263     m_streamProxy->close();
    264 
     245
     246     m_error = FileError::create(httpStatusCodeToExceptionCode(httpStatusCode));
    265247    fireEvent(eventNames().errorEvent);
    266248    fireEvent(eventNames().loadendEvent);
     249
     250    m_loader = 0;
     251}
     252
     253ExceptionCode FileReader::httpStatusCodeToExceptionCode(int httpStatusCode)
     254{
     255    switch (httpStatusCode) {
     256        case 403:
     257            return SECURITY_ERR;
     258        case 404:
     259            return NOT_FOUND_ERR;
     260        default:
     261            return NOT_READABLE_ERR;
     262    }
    267263}
    268264
     
    304300    // For data URL, we only do the coversion until we receive all the raw data.
    305301    else if (m_readType == ReadFileAsDataURL && m_state == Completed)
    306         convertToDataURL();
     302        convertToDataURL(m_rawData, m_fileType, m_result);
    307303
    308304    return m_result;
     
    329325}
    330326
    331 void FileReader::convertToDataURL()
    332 {
    333     m_result = "data:";
    334 
    335     if (!m_rawData.size())
    336         return;
    337 
    338     m_result += m_fileType;
    339     if (!m_fileType.isEmpty())
    340         m_result += ";";
    341     m_result += "base64,";
     327void FileReader::convertToDataURL(const Vector<char>& rawData, const String& fileType, ScriptString& result)
     328{
     329    result = "data:";
     330
     331    if (!rawData.size())
     332        return;
     333
     334    result += fileType;
     335    if (!fileType.isEmpty())
     336        result += ";";
     337    result += "base64,";
    342338
    343339    Vector<char> out;
    344     base64Encode(m_rawData, out);
     340    base64Encode(rawData, out);
    345341    out.append('\0');
    346     m_result += out.data();
     342    result += out.data();
    347343}
    348344
  • trunk/WebCore/fileapi/FileReader.h

    r66365 r66452  
    3737#include "EventTarget.h"
    3838#include "FileError.h"
    39 #include "FileStreamClient.h"
    4039#include "PlatformString.h"
    4140#include "ScriptString.h"
    4241#include "TextEncoding.h"
     42#include "ThreadableLoaderClient.h"
    4343#include <wtf/PassRefPtr.h>
    4444#include <wtf/RefCounted.h>
     
    4949
    5050class Blob;
    51 class File;
    52 class FileStreamProxy;
    5351class ScriptExecutionContext;
    5452class TextResourceDecoder;
     53class ThreadableLoader;
    5554
    56 class FileReader : public RefCounted<FileReader>, public ActiveDOMObject, public EventTarget, public FileStreamClient {
     55class FileReader : public RefCounted<FileReader>, public ActiveDOMObject, public EventTarget, public ThreadableLoaderClient {
    5756public:
    5857    static PassRefPtr<FileReader> create(ScriptExecutionContext* context)
     
    7170    void readAsBinaryString(Blob*);
    7271    void readAsText(Blob*, const String& encoding = "");
    73     void readAsDataURL(File*);
     72    void readAsDataURL(Blob*);
    7473    void abort();
     74
     75    void start();
    7576
    7677    ReadyState readyState() const;
    7778    PassRefPtr<FileError> error() { return m_error; }
    7879    const ScriptString& result();
     80
     81    // Helper methods, also used by FileReaderSync.
     82    static ExceptionCode httpStatusCodeToExceptionCode(int httpStatusCode);
     83    static void convertToDataURL(const Vector<char>& rawData, const String& fileType, ScriptString& result);
    7984
    8085    // ActiveDOMObject
     
    8792    virtual ScriptExecutionContext* scriptExecutionContext() const { return ActiveDOMObject::scriptExecutionContext(); }
    8893
    89     // FileStreamClient
    90     virtual void didStart();
    91     virtual void didGetSize(long long);
    92     virtual void didOpen(bool);
    93     virtual void didRead(int);
     94    // ThreadableLoaderClient
     95    virtual void didReceiveResponse(const ResourceResponse&);
     96    virtual void didReceiveData(const char*, int);
     97    virtual void didFinishLoading(unsigned long identifier);
     98    virtual void didFail(const ResourceError&);
    9499
    95100    using RefCounted<FileReader>::ref;
     
    127132    void terminate();
    128133    void readInternal(Blob*, ReadType);
     134    void failed(int httpStatusCode);
     135    void fireErrorEvent(int httpStatusCode);
    129136    void fireEvent(const AtomicString& type);
    130137    void convertToText();
    131138    void convertToDataURL();
    132     void didFinish();
    133     void didFail(ExceptionCode);
    134139
    135140    InternalState m_state;
    136141    EventTargetData m_eventTargetData;
    137142
    138     RefPtr<Blob> m_fileBlob;
     143    RefPtr<Blob> m_blob;
    139144    ReadType m_readType;
    140145    TextEncoding m_encoding;
     
    158163    String m_fileType;
    159164
    160     RefPtr<FileStreamProxy> m_streamProxy;
    161     Vector<char> m_buffer;
     165    RefPtr<ThreadableLoader> m_loader;
    162166    RefPtr<FileError> m_error;
    163167    long long m_bytesLoaded;
  • trunk/WebCore/html/FormDataList.cpp

    r63343 r66452  
    3434{
    3535    CString cstr = m_encoding.encode(s.characters(), s.length(), EntitiesForUnencodables);
    36     m_items.append(StringBlobItem::create(normalizeLineEndingsToCRLF(cstr)));
     36    m_items.append(normalizeLineEndingsToCRLF(cstr));
    3737}
    3838
    3939void FormDataList::appendString(const CString& s)
    4040{
    41     m_items.append(StringBlobItem::create(s));
     41    m_items.append(s);
    4242}
    4343
    44 void FormDataList::appendBlob(const String& key, PassRefPtr<Blob> blob)
     44void FormDataList::appendBlob(PassRefPtr<Blob> blob)
    4545{
    46     appendString(key);
    47     const BlobItemList& items = blob->items();
    48     for (size_t i = 0; i < items.size(); ++i)
    49         m_items.append(items.at(i));
     46    m_items.append(blob);
    5047}
    5148
  • trunk/WebCore/html/FormDataList.h

    r65021 r66452  
    3131class FormDataList {
    3232public:
     33    class Item {
     34    public:
     35        Item() { }
     36        Item(const WTF::CString& data) : m_data(data) { }
     37        Item(PassRefPtr<Blob> blob) : m_blob(blob) { }
     38
     39        const WTF::CString& data() const { return m_data; }
     40        Blob* blob() const { return m_blob.get(); }
     41
     42    private:
     43        WTF::CString m_data;
     44        RefPtr<Blob> m_blob;
     45    };
     46
    3347    FormDataList(const TextEncoding&);
    3448
     
    4862        appendString(String::number(value));
    4963    }
    50     void appendBlob(const String& key, PassRefPtr<Blob>);
     64    void appendBlob(const String& key, PassRefPtr<Blob> blob)
     65    {
     66        appendString(key);
     67        appendBlob(blob);
     68    }
    5169
    52     const BlobItemList& items() const { return m_items; }
     70    const Vector<Item>& items() const { return m_items; }
    5371    const TextEncoding& encoding() const { return m_encoding; }
    5472
     
    5674    void appendString(const CString&);
    5775    void appendString(const String&);
     76    void appendBlob(PassRefPtr<Blob>);
    5877
    5978    TextEncoding m_encoding;
    60     BlobItemList m_items;
     79    Vector<Item> m_items;
    6180};
    6281
  • trunk/WebCore/loader/FormSubmission.cpp

    r65340 r66452  
    163163
    164164    if (isMultiPartForm) {
    165         formData = FormData::createMultiPart(domFormData->items(), domFormData->encoding(), document);
     165        formData = FormData::createMultiPart(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), document);
    166166        boundary = formData->boundary().data();
    167167    } else {
    168         formData = FormData::create(domFormData->items(), domFormData->encoding());
     168        formData = FormData::create(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding());
    169169        if (attributes.method() == PostMethod && isMailtoForm) {
    170170            // Convert the form data into a string that we put into the URL.
  • trunk/WebCore/platform/network/BlobRegistryImpl.cpp

    r65827 r66452  
    3333#include "BlobRegistryImpl.h"
    3434
     35#include "BlobResourceHandle.h"
    3536#include "ResourceError.h"
    3637#include "ResourceHandle.h"
     
    6162}
    6263
    63 PassRefPtr<ResourceHandle> BlobRegistryImpl::createResourceHandle(const ResourceRequest& request, ResourceHandleClient*)
     64PassRefPtr<ResourceHandle> BlobRegistryImpl::createResourceHandle(const ResourceRequest& request, ResourceHandleClient* client)
    6465{
    6566    if (!shouldLoadResource(request))
    6667        return 0;
    6768
    68     // FIXME: To be implemented.
    69     return 0;
     69    return BlobResourceHandle::create(m_blobs.get(request.url().string()), request, client);
    7070}
    7171
    72 bool BlobRegistryImpl::loadResourceSynchronously(const ResourceRequest& request, ResourceError&, ResourceResponse&, Vector<char>&)
     72bool BlobRegistryImpl::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
    7373{
    7474    if (!shouldLoadResource(request))
    7575        return false;
    7676
    77     // FIXME: To be implemented.
    78     return false;
     77    BlobResourceHandle::loadResourceSynchronously(m_blobs.get(request.url().string()), request, error, response, data);
     78    return true;
    7979}
    8080
  • trunk/WebCore/platform/network/BlobResourceHandle.cpp

    r65827 r66452  
    160160{   
    161161    if (m_async) {
    162         m_asyncStream = adoptRef(client->createAsyncFileStream(this));
     162        // We need to take a ref.
     163        m_asyncStream = client->createAsyncFileStream(this);
    163164        callOnMainThread(delayedStart, this);
    164165    } else
  • trunk/WebCore/platform/network/FormData.cpp

    r65786 r66452  
    2323#include "FormData.h"
    2424
    25 #include "BlobItem.h"
     25#include "BlobData.h"
     26#include "BlobURL.h"
    2627#include "Chrome.h"
    2728#include "ChromeClient.h"
    2829#include "Document.h"
     30#include "File.h"
    2931#include "FileSystem.h"
    3032#include "FormDataBuilder.h"
     33#include "FormDataList.h"
    3134#include "MIMETypeRegistry.h"
    3235#include "Page.h"
     
    3437
    3538namespace WebCore {
    36 
    37 #if ENABLE(BLOB)
    38 const long long FormDataElement::toEndOfFile = -1;
    39 const double FormDataElement::doNotCheckFileChange = 0;
    40 #endif
    4139
    4240inline FormData::FormData()
     
    10098}
    10199
    102 PassRefPtr<FormData> FormData::create(const BlobItemList& items, const TextEncoding& encoding)
    103 {
    104     RefPtr<FormData> result = create();
    105     result->appendKeyValuePairItems(items, encoding, false, 0);
    106     return result.release();
    107 }
    108 
    109 PassRefPtr<FormData> FormData::createMultiPart(const BlobItemList& items, const TextEncoding& encoding, Document* document)
    110 {
    111     RefPtr<FormData> result = create();
    112     result->appendKeyValuePairItems(items, encoding, true, document);
     100PassRefPtr<FormData> FormData::create(const FormDataList& list, const TextEncoding& encoding)
     101{
     102    RefPtr<FormData> result = create();
     103    result->appendKeyValuePairItems(list, encoding, false, 0);
     104    return result.release();
     105}
     106
     107PassRefPtr<FormData> FormData::createMultiPart(const FormDataList& list, const TextEncoding& encoding, Document* document)
     108{
     109    RefPtr<FormData> result = create();
     110    result->appendKeyValuePairItems(list, encoding, true, document);
    113111    return result.release();
    114112}
     
    163161{
    164162#if ENABLE(BLOB)
    165     m_elements.append(FormDataElement(filename, 0, FormDataElement::toEndOfFile, FormDataElement::doNotCheckFileChange, shouldGenerateFile));
     163    m_elements.append(FormDataElement(filename, 0, BlobDataItem::toEndOfFile, BlobDataItem::doNotCheckFileChange, shouldGenerateFile));
    166164#else
    167165    m_elements.append(FormDataElement(filename, shouldGenerateFile));
     
    169167}
    170168
    171 void FormData::appendItems(const BlobItemList& items)
    172 {
    173     for (BlobItemList::const_iterator iter(items.begin()); iter != items.end(); ++iter)
    174         appendItem(iter->get(), false);
    175 }
    176 
    177 void FormData::appendItem(const BlobItem* item, bool shouldGenerateFile)
    178 {
    179     const DataBlobItem* dataItem = item->toDataBlobItem();
    180     if (dataItem) {
    181         appendData(dataItem->data(), static_cast<size_t>(dataItem->size()));
    182         return;
    183     }
    184 
    185     const FileBlobItem* fileItem = item->toFileBlobItem();
    186     ASSERT(fileItem);
    187     if (fileItem->path().isEmpty()) {
    188         // If the path is empty do not add the item.
    189         return;
    190     }
    191 
    192 #if ENABLE(BLOB)
    193     const FileRangeBlobItem* fileRangeItem = item->toFileRangeBlobItem();
    194     if (fileRangeItem) {
    195         appendFileRange(fileItem->path(), fileRangeItem->start(), fileRangeItem->size(), fileRangeItem->snapshotModificationTime(), shouldGenerateFile);
    196         return;
    197     }
    198 #endif
    199 
    200     appendFile(fileItem->path(), shouldGenerateFile);
    201 }
    202 
    203169#if ENABLE(BLOB)
    204170void FormData::appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile)
     
    213179#endif
    214180
    215 void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEncoding& encoding, bool isMultiPartForm, Document* document)
     181void FormData::appendKeyValuePairItems(const FormDataList& list, const TextEncoding& encoding, bool isMultiPartForm, Document* document)
    216182{
    217183    if (isMultiPartForm)
     
    220186    Vector<char> encodedData;
    221187
     188    const Vector<FormDataList::Item>& items = list.items();
    222189    size_t formDataListSize = items.size();
    223190    ASSERT(!(formDataListSize % 2));
    224191    for (size_t i = 0; i < formDataListSize; i += 2) {
    225         const StringBlobItem* key = items[i]->toStringBlobItem();
    226         const BlobItem* value = items[i + 1].get();
    227         ASSERT(key);
     192        const FormDataList::Item& key = items[i];
     193        const FormDataList::Item& value = items[i + 1];
    228194        if (isMultiPartForm) {
    229195            Vector<char> header;
    230             FormDataBuilder::beginMultiPartHeader(header, m_boundary.data(), key->cstr());
     196            FormDataBuilder::beginMultiPartHeader(header, m_boundary.data(), key.data());
    231197
    232198            bool shouldGenerateFile = false;
    233             // If the current type is FILE, then we also need to include the filename
    234             const FileBlobItem* fileItem = value->toFileBlobItem();
    235             if (fileItem) {
    236                 const String& path = fileItem->path();
    237 
    238 #if ENABLE(DIRECTORY_UPLOAD)
    239                 String fileName = !fileItem->relativePath().isEmpty() ? fileItem->relativePath() : fileItem->name();
     199
     200            // If the current type is blob, then we also need to include the filename
     201            if (value.blob()) {
     202                String name;
     203                if (value.blob()->isFile()) {
     204                    // For file blob, use the filename (or relative path if it is present) as the name.
     205                    File* file = static_cast<File*>(value.blob());
     206#if ENABLE(DIRECTORY_UPLOAD)               
     207                    name = file->webkitRelativePath().isEmpty() ? file->name() : file->webkitRelativePath();
    240208#else
    241                 String fileName = fileItem->name();
    242 #endif
    243 
    244                 // Let the application specify a filename if it's going to generate a replacement file for the upload.
    245                 if (!path.isEmpty()) {
     209                    name = file->name();
     210#endif                   
     211
     212                    // Let the application specify a filename if it's going to generate a replacement file for the upload.
    246213                    if (Page* page = document->page()) {
    247214                        String generatedFileName;
    248                         shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
     215                        shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(file->path(), generatedFileName);
    249216                        if (shouldGenerateFile)
    250                             fileName = generatedFileName;
     217                            name = generatedFileName;
    251218                    }
     219                } else {
     220                    // For non-file blob, use the identifier part of the URL as the name.
     221                    name = "Blob" + BlobURL::getIdentifier(value.blob()->url());
     222                    name = name.replace("-", ""); // For safety, remove '-' from the filename since some servers may not like it.
    252223                }
    253224
    254225                // We have to include the filename=".." part in the header, even if the filename is empty
    255                 FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, fileName);
    256 
    257                 // If the item is sliced from a file, do not add the content type.
    258 #if ENABLE(BLOB)
    259                 if (!fileName.isEmpty() && !value->toFileRangeBlobItem()) {
    260 #else
    261                 if (!fileName.isEmpty()) {
    262 #endif
    263                     // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path,
    264                     // not just a basename. But filename is not the path. But note that it's not safe to
    265                     // just use path instead since in the generated-file case it will not reflect the
    266                     // MIME type of the generated file.
    267                     String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName);
    268                     if (!mimeType.isEmpty())
    269                         FormDataBuilder::addContentTypeToMultiPartHeader(header, mimeType.latin1());
    270                 }
     226                FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, name);
     227
     228                // Add the content type if it is available.
     229                if (value.blob()->type().isEmpty())
     230                    FormDataBuilder::addContentTypeToMultiPartHeader(header, value.blob()->type().latin1());
    271231            }
    272232
     
    275235            // Append body
    276236            appendData(header.data(), header.size());
    277             appendItem(value, shouldGenerateFile);
     237            if (value.blob()) {
     238                if (value.blob()->isFile()) {
     239                    // Do not add the file if the path is empty.
     240                    if (!static_cast<File*>(value.blob())->path().isEmpty())
     241                        appendFile(static_cast<File*>(value.blob())->path(), shouldGenerateFile);
     242                }
     243#if ENABLE(BLOB)
     244                else
     245                    appendBlob(value.blob()->url());
     246#endif
     247            } else
     248                appendData(value.data().data(), value.data().length());
    278249            appendData("\r\n", 2);
    279250        } else {
    280251            // Omit the name "isindex" if it's the first form data element.
    281252            // FIXME: Why is this a good rule? Is this obsolete now?
    282             const StringBlobItem* stringValue = value->toStringBlobItem();
    283             if (!stringValue)
    284                 continue;
    285             if (encodedData.isEmpty() && key->cstr() == "isindex")
    286                 FormDataBuilder::encodeStringAsFormData(encodedData, stringValue->cstr());
     253            if (encodedData.isEmpty() && key.data() == "isindex")
     254                FormDataBuilder::encodeStringAsFormData(encodedData, value.data());
    287255            else
    288                 FormDataBuilder::addKeyValuePairAsFormData(encodedData, key->cstr(), stringValue->cstr());
     256                FormDataBuilder::addKeyValuePairAsFormData(encodedData, key.data(), value.data());
    289257        }
    290258    }
  • trunk/WebCore/platform/network/FormData.h

    r65786 r66452  
    2929namespace WebCore {
    3030
    31 class BlobItem;
    3231class Document;
     32class FormDataList;
    3333class TextEncoding;
    34 typedef Vector<RefPtr<BlobItem> > BlobItemList;
    3534
    3635class FormDataElement {
     
    6362    String m_generatedFilename;
    6463    bool m_shouldGenerateFile;
    65 
    66 #if ENABLE(BLOB)
    67     static const long long toEndOfFile;
    68     static const double doNotCheckFileChange;
    69 #endif
    7064};
    7165
     
    10296    static PassRefPtr<FormData> create(const CString&);
    10397    static PassRefPtr<FormData> create(const Vector<char>&);
    104     static PassRefPtr<FormData> create(const BlobItemList&, const TextEncoding&);
    105     static PassRefPtr<FormData> createMultiPart(const BlobItemList&, const TextEncoding&, Document*);
     98    static PassRefPtr<FormData> create(const FormDataList&, const TextEncoding&);
     99    static PassRefPtr<FormData> createMultiPart(const FormDataList&, const TextEncoding&, Document*);
    106100    PassRefPtr<FormData> copy() const;
    107101    PassRefPtr<FormData> deepCopy() const;
     
    109103
    110104    void appendData(const void* data, size_t);
    111     void appendItems(const BlobItemList&);
    112     void appendFile(const String& filename, bool shouldGenerateFile = false);
     105    void appendFile(const String& filePath, bool shouldGenerateFile = false);
    113106#if ENABLE(BLOB)
    114107    void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false);
     
    138131    FormData(const FormData&);
    139132
    140     void appendItem(const BlobItem*, bool shouldGenerateFile);
    141     void appendKeyValuePairItems(const BlobItemList&, const TextEncoding&, bool isMultiPartForm, Document*);
     133    void appendKeyValuePairItems(const FormDataList&, const TextEncoding&, bool isMultiPartForm, Document*);
    142134
    143135    Vector<FormDataElement> m_elements;
  • trunk/WebCore/platform/network/mac/FormDataStreamMac.mm

    r64763 r66452  
    3232#import "FormDataStreamMac.h"
    3333
     34#import "BlobRegistryImpl.h"
    3435#import "FileSystem.h"
    3536#import "FormData.h"
     
    142143        form->currentStream = NULL;
    143144#if ENABLE(BLOB)
    144         form->currentStreamRangeLength = FormDataElement::toEndOfFile;
     145        form->currentStreamRangeLength = BlobDataItem::toEndOfFile;
    145146#endif
    146147    }
     
    170171#if ENABLE(BLOB)
    171172        // Check if the file has been changed or not if required.
    172         if (nextInput.m_expectedFileModificationTime != FormDataElement::doNotCheckFileChange) {
     173        if (nextInput.m_expectedFileModificationTime != BlobDataItem::doNotCheckFileChange) {
    173174            time_t fileModificationTime;
    174175            if (!getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime))
     
    226227    newInfo->currentStream = NULL;
    227228#if ENABLE(BLOB)
    228     newInfo->currentStreamRangeLength = FormDataElement::toEndOfFile;
     229    newInfo->currentStreamRangeLength = BlobDataItem::toEndOfFile;
    229230#endif
    230231    newInfo->currentData = 0;
     
    274275        CFIndex bytesToRead = bufferLength;
    275276#if ENABLE(BLOB)
    276         if (form->currentStreamRangeLength != FormDataElement::toEndOfFile && form->currentStreamRangeLength < bytesToRead)
     277        if (form->currentStreamRangeLength != BlobDataItem::toEndOfFile && form->currentStreamRangeLength < bytesToRead)
    277278            bytesToRead = static_cast<CFIndex>(form->currentStreamRangeLength);
    278279#endif
     
    287288            form->bytesSent += bytesRead;
    288289#if ENABLE(BLOB)
    289             if (form->currentStreamRangeLength != FormDataElement::toEndOfFile)
     290            if (form->currentStreamRangeLength != BlobDataItem::toEndOfFile)
    290291                form->currentStreamRangeLength -= bytesRead;
    291292#endif
     
    395396    }
    396397
     398#if ENABLE(BLOB)
     399    // Check if there is a blob in the form data.
     400    bool hasBlob = false;
     401    for (size_t i = 0; i < count; ++i) {
     402        const FormDataElement& element = formData->elements()[i];
     403        if (element.m_type == FormDataElement::encodedBlob) {
     404            hasBlob = true;
     405            break;
     406        }
     407    }
     408
     409    // If yes, we have to resolve all the blob references and regenerate the form data with only data and file types.
     410    if (hasBlob) {
     411        RefPtr<FormData> newFormData = FormData::create();
     412        newFormData->setAlwaysStream(formData->alwaysStream());
     413        newFormData->setIdentifier(formData->identifier());
     414        for (size_t i = 0; i < count; ++i) {
     415            const FormDataElement& element = formData->elements()[i];
     416            if (element.m_type == FormDataElement::data)
     417                newFormData->appendData(element.m_data.data(), element.m_data.size());
     418            else if (element.m_type == FormDataElement::encodedFile)
     419                newFormData->appendFile(element.m_filename, element.m_shouldGenerateFile);
     420            else {
     421                ASSERT(element.m_type == FormDataElement::encodedBlob);
     422                RefPtr<BlobStorageData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(KURL(ParsedURLString, element.m_blobURL));
     423                if (blobData) {
     424                    for (size_t j = 0; j < blobData->items().size(); ++j) {
     425                        const BlobDataItem& blobItem = blobData->items()[j];
     426                        if (blobItem.type == BlobDataItem::Data) {
     427                            newFormData->appendData(blobItem.data.data() + static_cast<int>(blobItem.offset), static_cast<int>(blobItem.length));
     428                        } else {
     429                            ASSERT(blobItem.type == BlobDataItem::File);
     430                            newFormData->appendFileRange(blobItem.path, blobItem.offset, blobItem.length, blobItem.expectedModificationTime);
     431                        }
     432                    }
     433                }
     434            }
     435        }
     436        formData = newFormData;
     437        count = formData->elements().size();
     438    }
     439#endif
     440
    397441    // Precompute the content length so NSURLConnection doesn't use chunked mode.
    398442    long long length = 0;
     
    404448#if ENABLE(BLOB)
    405449            // If we're sending the file range, use the existing range length for now. We will detect if the file has been changed right before we read the file and abort the operation if necessary.
    406             if (element.m_fileLength != FormDataElement::toEndOfFile) {
     450            if (element.m_fileLength != BlobDataItem::toEndOfFile) {
    407451                length += element.m_fileLength;
    408452                continue;
  • trunk/WebCore/xml/XMLHttpRequest.cpp

    r66243 r66452  
    523523        // FIXME: add support for uploading bundles.
    524524        m_requestEntityBody = FormData::create();
    525         m_requestEntityBody->appendItems(body->items());
     525        m_requestEntityBody->appendBlob(body->url());
    526526    }
    527527
     
    535535
    536536    if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
    537         m_requestEntityBody = FormData::createMultiPart(body->items(), body->encoding(), document());
     537        m_requestEntityBody = FormData::createMultiPart(*(static_cast<FormDataList*>(body)), body->encoding(), document());
    538538
    539539        // We need to ask the client to provide the generated file names if needed. When FormData fills the element
  • trunk/WebKit/chromium/ChangeLog

    r66450 r66452  
     12010-08-31  Jian Li  <jianli@chromium.org>
     2
     3        Reviewed by Darin Fisher.
     4
     5        Switch the Blob implementation to using the blob data registration model
     6        https://bugs.webkit.org/show_bug.cgi?id=44389
     7
     8        * src/WebSearchableFormData.cpp:
     9        (WebCore::HasSuitableTextElement):
     10
    1112010-08-30  Nat Duca  <nduca@chromium.org>
    212
  • trunk/WebKit/chromium/src/WebSearchableFormData.cpp

    r60799 r66452  
    188188          continue;
    189189
    190       const BlobItemList& items = dataList.items();
     190      const Vector<FormDataList::Item>& items = dataList.items();
    191191      if (isTextElement && !items.isEmpty()) {
    192192          if (textElement) {
     
    197197          textElement = static_cast<HTMLInputElement*>(formElement);
    198198      }
    199       for (BlobItemList::const_iterator j(items.begin()); j != items.end(); ++j) {
    200           const StringBlobItem* item = (*j)->toStringBlobItem();
    201           ASSERT(item);
     199      for (Vector<FormDataList::Item>::const_iterator j(items.begin()); j != items.end(); ++j) {
    202200          // Handle ISINDEX / <input name=isindex> specially, but only if it's
    203201          // the first entry.
    204           if (!encodedString->isEmpty() || item->cstr() != "isindex") {
     202          if (!encodedString->isEmpty() || j->data() != "isindex") {
    205203              if (!encodedString->isEmpty())
    206204                  encodedString->append('&');
    207               FormDataBuilder::encodeStringAsFormData(*encodedString, item->cstr());
     205              FormDataBuilder::encodeStringAsFormData(*encodedString, j->data());
    208206              encodedString->append('=');
    209207          }
     
    212210              encodedString->append("{searchTerms}", 13);
    213211          else
    214               FormDataBuilder::encodeStringAsFormData(*encodedString, item->cstr());
     212              FormDataBuilder::encodeStringAsFormData(*encodedString, j->data());
    215213      }
    216214    }
Note: See TracChangeset for help on using the changeset viewer.