.: Blob.slice support.
authorjianli@chromium.org <jianli@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Mar 2010 18:13:31 +0000 (18:13 +0000)
committerjianli@chromium.org <jianli@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Mar 2010 18:13:31 +0000 (18:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

Add ENABLE_BLOB_SLICE feature define.

* configure.ac:

JavaScriptCore: Blob.slice support.
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

Add ENABLE_BLOB_SLICE feature define.
Also fix a problem that JSValue.toInteger is not exposed on Windows.

* Configurations/FeatureDefines.xcconfig:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:

WebCore: Blob.slice support.
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

The following semantic is adopted per the discussions on public-webapps:
1) File.slice() does a synchronous IO to capture the current size and
   modification time and cache them in the resulting Blob.
2) Subsequent Blob operations, like Blob.slice and Blob.size simply
   use the cached values.
3) When the underlying file data are accessed, like in XHR.send(), the
   UA will check the cached modification time against the current
   modification time to determine if the file has been changed or not.
   An error or exception will be thrown if needed.

Also add ENABLE_BLOB_SLICE feature define.

Test: http/tests/local/send-sliced-dragged-file.html

* Configurations/FeatureDefines.xcconfig:
* GNUmakefile.am:
* WebCore.pri:
* html/Blob.cpp:
(WebCore::Blob::Blob):
(WebCore::Blob::size):
(WebCore::Blob::slice):
* html/Blob.h:
(WebCore::Blob::start):
(WebCore::Blob::length):
(WebCore::Blob::modificationTime):
* html/Blob.idl:
* platform/network/FormData.cpp:
(WebCore::FormData::deepCopy):
(WebCore::FormData::appendFile):
(WebCore::FormData::appendFileRange):
* platform/network/FormData.h:
(WebCore::FormDataElement::FormDataElement):
(WebCore::operator==):
* platform/network/mac/FormDataStreamMac.mm:
(WebCore::advanceCurrentStream):
(WebCore::openNextStream):
(WebCore::formCreate):
(WebCore::formOpen):
(WebCore::formRead):
(WebCore::setHTTPBody):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::send):

WebKit/chromium: Blob.slice support.
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

Add ENABLE_BLOB_SLICE feature define.

* features.gypi:

WebKit/mac: Blob.slice support.
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

Add ENABLE_BLOB_SLICE feature define.

* Configurations/FeatureDefines.xcconfig:

WebKitLibraries: Blob.slice support.
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

Add ENABLE_BLOB_SLICE feature define.

* win/tools/vsprops/FeatureDefines.vsprops:
* win/tools/vsprops/FeatureDefinesCairo.vsprops:

WebKitTools: Blob.slice support.
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

Add ENABLE_BLOB_SLICE feature define and  flag for build-webkit. It is
currently only turned on for Mac.

* Scripts/build-webkit:

LayoutTests: Blob.slice support.
https://bugs.webkit.org/show_bug.cgi?id=32993

Reviewed by Dmitry Titov.

Add a new layout test to test slicing and sending a file. In addition,
two new scripts are introduced to create and touch the temp file.

Move some code from send-dragged-file.js to a new file
setup-file-input-element-for-drag.js so that it can be used by both
send-dragged-file.js and send-sliced-dragged-file.js to setup the input
element for the file dragging.

Since the Blob.slice is only enabled for Mac, we disable the new test
for all other platforms.

* fast/dom/Window/window-properties.html:
* http/tests/local/resources/file-for-drag-to-send.txt:
* http/tests/local/resources/send-dragged-file.js:
* http/tests/local/resources/send-sliced-dragged-file.js: Added.
* http/tests/local/resources/setup-file-input-element-for-drag.js: Added.
* http/tests/local/send-dragged-file.html:
* http/tests/local/send-sliced-dragged-file-expected.txt: Added.
* http/tests/local/send-sliced-dragged-file.html: Added.
* http/tests/resources/touch-temp-file.php: Added.
* http/tests/resources/write-temp-file.php: Added.
* platform/gtk/Skipped:
* platform/qt/Skipped:
* platform/win/Skipped:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@55670 268f45cc-cd09-0410-ab3c-d52691b4dbfc

39 files changed:
ChangeLog
JavaScriptCore/ChangeLog
JavaScriptCore/Configurations/FeatureDefines.xcconfig
JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
LayoutTests/ChangeLog
LayoutTests/fast/dom/Window/window-properties.html
LayoutTests/http/tests/local/resources/file-for-drag-to-send.txt
LayoutTests/http/tests/local/resources/send-dragged-file.js
LayoutTests/http/tests/local/resources/send-sliced-dragged-file.js [new file with mode: 0644]
LayoutTests/http/tests/local/resources/setup-file-input-element-for-drag.js [new file with mode: 0644]
LayoutTests/http/tests/local/send-dragged-file.html
LayoutTests/http/tests/local/send-sliced-dragged-file-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/local/send-sliced-dragged-file.html [new file with mode: 0644]
LayoutTests/http/tests/resources/touch-temp-file.php [new file with mode: 0644]
LayoutTests/http/tests/resources/write-temp-file.php [new file with mode: 0644]
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/qt/Skipped
LayoutTests/platform/win/Skipped
WebCore/ChangeLog
WebCore/Configurations/FeatureDefines.xcconfig
WebCore/GNUmakefile.am
WebCore/WebCore.pri
WebCore/html/Blob.cpp
WebCore/html/Blob.h
WebCore/html/Blob.idl
WebCore/platform/network/FormData.cpp
WebCore/platform/network/FormData.h
WebCore/platform/network/mac/FormDataStreamMac.mm
WebCore/xml/XMLHttpRequest.cpp
WebKit/chromium/ChangeLog
WebKit/chromium/features.gypi
WebKit/mac/ChangeLog
WebKit/mac/Configurations/FeatureDefines.xcconfig
WebKitLibraries/ChangeLog
WebKitLibraries/win/tools/vsprops/FeatureDefines.vsprops
WebKitLibraries/win/tools/vsprops/FeatureDefinesCairo.vsprops
WebKitTools/ChangeLog
WebKitTools/Scripts/build-webkit
configure.ac

index a280392..38163b0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+
+        Add ENABLE_BLOB_SLICE feature define.
+
+        * configure.ac:
+
 2010-03-04  Fridrich Strba  <fridrich.strba@bluewin.ch>
 
         Reviewed by Holger Freyther.
index 20c4846..b9444ea 100644 (file)
@@ -1,3 +1,16 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+
+        Add ENABLE_BLOB_SLICE feature define.
+        Also fix a problem that JSValue.toInteger is not exposed on Windows.
+
+        * Configurations/FeatureDefines.xcconfig:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+
 2010-03-07  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
 
         Reviewed by Simon Hausmann.
index 4c4e193..eb96c27 100644 (file)
@@ -41,6 +41,7 @@ ENABLE_3D_RENDERING_1050 = ENABLE_3D_RENDERING;
 ENABLE_3D_RENDERING_1060 = ENABLE_3D_RENDERING;
 ENABLE_3D_RENDERING_1070 = ENABLE_3D_RENDERING;
 
+ENABLE_BLOB_SLICE = ENABLE_BLOB_SLICE;
 ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
 ENABLE_CLIENT_BASED_GEOLOCATION = ENABLE_CLIENT_BASED_GEOLOCATION;
 ENABLE_DATABASE = ENABLE_DATABASE;
@@ -74,4 +75,4 @@ ENABLE_XHTMLMP = ;
 ENABLE_XPATH = ENABLE_XPATH;
 ENABLE_XSLT = ENABLE_XSLT;
 
-FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
+FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
index 0818a3e..219bcfd 100644 (file)
@@ -272,6 +272,7 @@ EXPORTS
     ?toBoolean@JSObject@JSC@@UBE_NPAVExecState@2@@Z
     ?toBoolean@JSString@JSC@@EBE_NPAVExecState@2@@Z
     ?toInt32SlowCase@JSC@@YAHNAA_N@Z
+    ?toInteger@JSValue@JSC@@QBENPAVExecState@2@@Z
     ?toNumber@JSCell@JSC@@UBENPAVExecState@2@@Z
     ?toNumber@JSObject@JSC@@UBENPAVExecState@2@@Z
     ?toNumber@JSString@JSC@@EBENPAVExecState@2@@Z
index 0e51907..68ba559 100644 (file)
@@ -1,3 +1,35 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+
+        Add a new layout test to test slicing and sending a file. In addition,
+        two new scripts are introduced to create and touch the temp file.
+
+        Move some code from send-dragged-file.js to a new file
+        setup-file-input-element-for-drag.js so that it can be used by both
+        send-dragged-file.js and send-sliced-dragged-file.js to setup the input
+        element for the file dragging.
+
+        Since the Blob.slice is only enabled for Mac, we disable the new test
+        for all other platforms.
+
+        * fast/dom/Window/window-properties.html:
+        * http/tests/local/resources/file-for-drag-to-send.txt:
+        * http/tests/local/resources/send-dragged-file.js:
+        * http/tests/local/resources/send-sliced-dragged-file.js: Added.
+        * http/tests/local/resources/setup-file-input-element-for-drag.js: Added.
+        * http/tests/local/send-dragged-file.html:
+        * http/tests/local/send-sliced-dragged-file-expected.txt: Added.
+        * http/tests/local/send-sliced-dragged-file.html: Added.
+        * http/tests/resources/touch-temp-file.php: Added.
+        * http/tests/resources/write-temp-file.php: Added.
+        * platform/gtk/Skipped:
+        * platform/qt/Skipped:
+        * platform/win/Skipped:
+
 2010-03-08  Daniel Bates  <dbates@rim.com>
 
         Reviewed by Simon Fraser.
index 03e6478..a5e00b6 100644 (file)
@@ -71,7 +71,8 @@ var __skip__ = {
     "window.WebGLUnsignedByteArray" : 1, 
     "window.WebGLUnsignedIntArray" : 1, 
     "window.WebGLUnsignedShortArray" : 1,
-    "window.clientInformation.geolocation" : 1
+    "window.clientInformation.geolocation" : 1,
+    "window.Blob.prototype.slice" : 1
 };
 
 function logValue(valueName)
index bed4078..efc1124 100644 (file)
@@ -1,48 +1,21 @@
 description("Test for sending a dragged file via XMLHttpRequest.");
 
-var fileInput = document.createElement("input");
-fileInput.type = "file";
-fileInput.style.width = "100px";
-fileInput.style.height = "100px";
-// Important that we put this at the top of the doc so that logging does not cause it to go out of view (where it can't be dragged to)
-document.body.insertBefore(fileInput, document.body.firstChild);
-
-fileInput.addEventListener("dragenter", function() {
-    event.preventDefault();
-}, false);
-
-fileInput.addEventListener("dragover", function() {
-    event.dataTransfer.dropEffect = "copy";
-    event.preventDefault();
-}, false);
-
-fileInput.addEventListener("drop", function() {
-    if (event.dataTransfer.types.indexOf("Files") != -1 && event.dataTransfer.files.length == 1)
-        testPassed("event.dataTransfer contains a File object on drop.");
-    else {
-        testFailed("event.dataTransfer does not contain a File object on drop.");
-        return;
-    }
-
+function onFileDrop(file)
+{
     var xhr = new XMLHttpRequest();
     xhr.open("POST", "http://127.0.0.1:8000/xmlhttprequest/resources/post-echo.cgi", false);
-    xhr.send(event.dataTransfer.files[0]);
-    if (xhr.responseText == "Hello")
+    xhr.send(file);
+    if (xhr.responseText == "1234567890")
         testPassed("Expected response data received.");
     else
         testFailed("Unexpected response data received: " + xhr.responseText);
 
     event.preventDefault();
-}, false);
-
-function moveMouseToCenterOfElement(element) {
-    var centerX = element.offsetLeft + element.offsetWidth / 2;
-    var centerY = element.offsetTop + element.offsetHeight / 2;
-    eventSender.mouseMoveTo(centerX, centerY);
 }
 
 function runTest()
 {
+    setFileInputDropCallback(onFileDrop);
     eventSender.beginDragWithFiles(["resources/file-for-drag-to-send.txt"]);
     moveMouseToCenterOfElement(fileInput);
     eventSender.mouseUp();
@@ -51,7 +24,7 @@ function runTest()
 if (window.eventSender) {
     runTest();
     // Clean up after ourselves
-    fileInput.parentNode.removeChild(fileInput);
+    removeFileInputElement();
 } else {
     testFailed("This test is not interactive, please run using DumpRenderTree");
 }
diff --git a/LayoutTests/http/tests/local/resources/send-sliced-dragged-file.js b/LayoutTests/http/tests/local/resources/send-sliced-dragged-file.js
new file mode 100644 (file)
index 0000000..c2289a8
--- /dev/null
@@ -0,0 +1,150 @@
+description("Test for slicing a dragged file and sending it via XMLHttpRequest.");
+
+var originalText = "1234567890";
+var tempFileName = "send-slice-dragged-file.tmp";
+var tempFileOriginalModificationTime;
+var subfile;
+
+function uploadFile(file, expectedText, expectedException)
+{
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", "http://127.0.0.1:8000/xmlhttprequest/resources/post-echo.cgi", false);
+
+    var passed;
+    var message;
+    try {
+        xhr.send(file);
+        if (expectedException) {
+            passed = false;
+            message = "Unexpected response data received: " + xhr.responseText + ". Expecting exception thrown";
+        } else {
+            if (xhr.responseText == expectedText) {
+                passed = true;
+                message = "Expected response data received: " + xhr.responseText;
+            } else {
+                passed = false;
+                message = "Unexpected response data received: " + xhr.responseText + ". Expecting: " + expectedText;
+            }
+        }
+    } catch (ex) {
+        if (expectedException) {
+            passed = true;
+            message = "Expected exception thrown: " + ex;
+        } else {
+            passed = false;
+            message = "Unexpected exception thrown: " + ex;
+        }
+    }
+
+    if (passed)
+        testPassed(message);
+    else
+        testFailed(message);
+}
+
+function createTempFile(fileData)
+{
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", "http://127.0.0.1:8000/resources/write-temp-file.php?filename=" + tempFileName + "&data=" + fileData, false);
+    xhr.send();
+    if (xhr.status != 200) {
+        testFailed("Unexpected response status received: " + xhr.status);
+        return;
+    }
+
+    var values = xhr.responseText.split('\n');
+    if (values.length < 2) {
+        testFailed("Unexpected response text received: " + xhr.responseText);
+        return;
+    }
+
+    return values;
+}
+
+function touchTempFile()
+{
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", "http://127.0.0.1:8000/resources/touch-temp-file.php?filename=" + tempFileName, false);
+    xhr.send();
+}
+
+function removeTempFile()
+{
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", "http://127.0.0.1:8000/resources/reset-temp-file.php?filename=" + tempFileName, false);
+    xhr.send();
+}
+
+function onStableFileDrop(file, start, length)
+{
+    // Slice the file.
+    subfile = file.slice(start, length);
+    var expectedText = originalText.substring(start, start + length);
+    shouldEvaluateTo("subfile.size", expectedText.length);
+
+    // Upload the sliced file.
+    uploadFile(subfile, expectedText, false);
+}
+
+function dragAndSliceStableFile(start, length)
+{
+    setFileInputDropCallback(function(file) { onStableFileDrop(file, start, length); });
+    eventSender.beginDragWithFiles(["resources/file-for-drag-to-send.txt"]);
+    moveMouseToCenterOfElement(fileInput);
+    eventSender.mouseUp();
+}
+
+function onUnstableFileDrop(file, start, length)
+{
+    // Slice the file.
+    subfile = file.slice(start, length);
+    var expectedText = originalText.substring(start, start + length);
+    shouldEvaluateTo("subfile.size", expectedText.length);
+  
+    // Upload the sliced file.
+    uploadFile(subfile, expectedText, false);
+
+    // Touch the underlying temp file.
+    touchTempFile();
+    
+    // Upload the sliced file. We should receive an exception since the file has been changed.
+    uploadFile(subfile, null, true);
+
+    // Remove the temp file.
+    removeTempFile();
+}
+
+function dragAndSliceUnstableFile(start, length)
+{
+    var tempFileInfo = createTempFile(originalText);
+    if (tempFileInfo.length < 2) {
+        done();
+        return;
+    }
+    var tempFilePath = tempFileInfo[0];
+    tempFileOriginalModificationTime = tempFileInfo[1];
+
+    setFileInputDropCallback(function(file) { onUnstableFileDrop(file, start, length); });
+    eventSender.beginDragWithFiles([tempFilePath]);
+    moveMouseToCenterOfElement(fileInput);
+    eventSender.mouseUp();
+}
+
+function runTest()
+{
+    dragAndSliceStableFile(2, 4);
+    dragAndSliceStableFile(2, 20);
+    dragAndSliceStableFile(15, 20);
+
+    dragAndSliceUnstableFile(3, 5);
+}
+
+if (window.eventSender) {
+    runTest();
+    // Clean up after ourselves
+    removeFileInputElement();
+} else {
+    testFailed("This test is not interactive, please run using DumpRenderTree");
+}
+
+var successfullyParsed = true;
diff --git a/LayoutTests/http/tests/local/resources/setup-file-input-element-for-drag.js b/LayoutTests/http/tests/local/resources/setup-file-input-element-for-drag.js
new file mode 100644 (file)
index 0000000..c51c680
--- /dev/null
@@ -0,0 +1,46 @@
+var fileInput = document.createElement("input");
+fileInput.type = "file";
+fileInput.style.width = "100px";
+fileInput.style.height = "100px";
+// Important that we put this at the top of the doc so that logging does not cause it to go out of view (where it can't be dragged to)
+document.body.insertBefore(fileInput, document.body.firstChild);
+
+fileInput.addEventListener("dragenter", function() {
+    event.preventDefault();
+}, false);
+
+fileInput.addEventListener("dragover", function() {
+    event.dataTransfer.dropEffect = "copy";
+    event.preventDefault();
+}, false);
+
+var fileInputDropCallback = null;
+fileInput.addEventListener("drop", function() {
+    if (event.dataTransfer.types.indexOf("Files") != -1 && event.dataTransfer.files.length == 1)
+        testPassed("event.dataTransfer contains a File object on drop.");
+    else {
+        testFailed("event.dataTransfer does not contain a File object on drop.");
+        return;
+    }
+
+    fileInputDropCallback(event.dataTransfer.files[0]);
+
+    event.preventDefault();
+}, false);
+
+function setFileInputDropCallback(fileInputDropCallbackFunc)
+{
+    fileInputDropCallback = fileInputDropCallbackFunc;
+}
+
+function moveMouseToCenterOfElement(element)
+{
+    var centerX = element.offsetLeft + element.offsetWidth / 2;
+    var centerY = element.offsetTop + element.offsetHeight / 2;
+    eventSender.mouseMoveTo(centerX, centerY);
+}
+
+function removeFileInputElement()
+{
+    fileInput.parentNode.removeChild(fileInput)
+}
index 3f2210a..f5280f4 100644 (file)
@@ -7,6 +7,7 @@
 <body>
 <p id="description"></p>
 <div id="console"></div>
+<script src="resources/setup-file-input-element-for-drag.js"></script>
 <script src="resources/send-dragged-file.js"></script>
 <script src="../../../fast/js/resources/js-test-post.js"></script>
 </body>
diff --git a/LayoutTests/http/tests/local/send-sliced-dragged-file-expected.txt b/LayoutTests/http/tests/local/send-sliced-dragged-file-expected.txt
new file mode 100644 (file)
index 0000000..b460791
--- /dev/null
@@ -0,0 +1,22 @@
+Test for slicing a dragged file and sending it via XMLHttpRequest.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS event.dataTransfer contains a File object on drop.
+PASS subfile.size is 4
+PASS Expected response data received: 3456
+PASS event.dataTransfer contains a File object on drop.
+PASS subfile.size is 8
+PASS Expected response data received: 34567890
+PASS event.dataTransfer contains a File object on drop.
+PASS subfile.size is 0
+PASS Expected response data received: 
+PASS event.dataTransfer contains a File object on drop.
+PASS subfile.size is 5
+PASS Expected response data received: 45678
+PASS Expected exception thrown: Error: NETWORK_ERR: XMLHttpRequest Exception 101
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/local/send-sliced-dragged-file.html b/LayoutTests/http/tests/local/send-sliced-dragged-file.html
new file mode 100644 (file)
index 0000000..c041b1f
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../../fast/js/resources/js-test-style.css">
+<script src="../../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/setup-file-input-element-for-drag.js"></script>
+<script src="resources/send-sliced-dragged-file.js"></script>
+<script src="../../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/resources/touch-temp-file.php b/LayoutTests/http/tests/resources/touch-temp-file.php
new file mode 100644 (file)
index 0000000..d2829df
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+require_once 'portabilityLayer.php';
+
+if (!sys_get_temp_dir()) {
+    echo "FAIL: No temp dir was returned.\n";
+    exit();
+}
+
+$tmpFile = sys_get_temp_dir() . "/" . $_GET['filename'];
+
+$stat = stat($tmpFile);
+if (!$stat) {
+    echo "FAIL: stat() call failed.\n";
+    exit();
+}
+
+$mtime = $stat['mtime'] + 1;
+
+if (!touch($tmpFile, $mtime)) {
+    echo "FAIL: touch() call failed.\n";
+}
+?>
diff --git a/LayoutTests/http/tests/resources/write-temp-file.php b/LayoutTests/http/tests/resources/write-temp-file.php
new file mode 100644 (file)
index 0000000..ffe2c8c
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+require_once 'portabilityLayer.php';
+
+if (!sys_get_temp_dir()) {
+    echo "FAIL: No temp dir was returned.\n";
+    exit();
+}
+
+$tmpFile = sys_get_temp_dir() . "/" . $_GET['filename'];
+
+if (!file_put_contents($tmpFile, $_GET['data'])) {
+    echo "FAIL: unable to write to file: " . $tmpFile . "\n";
+    exit();
+}
+
+$stat = stat($tmpFile);
+
+echo $tmpFile . "\n";
+echo $stat['mtime'];
+?>
index 6723218..8891801 100644 (file)
@@ -3421,6 +3421,7 @@ http/tests/loading/preload-img-test.html
 http/tests/loading/slow-parsing-subframe.html
 http/tests/loading/text-content-type-with-binary-extension.html
 http/tests/local/send-dragged-file.html
+http/tests/local/send-sliced-dragged-file.html
 http/tests/media/video-play-stall-seek.html
 http/tests/media/video-play-stall.html
 http/tests/media/video-seekable-stall.html
index 0df3ab6..184f476 100644 (file)
@@ -53,6 +53,7 @@ plugins/set-status.html
 # Failing Local tests
 http/tests/local/drag-over-remote-content.html
 http/tests/local/send-dragged-file.html
+http/tests/local/send-sliced-dragged-file.html
 
 # Failing navigation tests
 http/tests/navigation/anchor-frames.html
index 4047618..90f9f70 100644 (file)
@@ -660,6 +660,7 @@ fast/forms/input-selectedoption.html
 
 # <https://bugs.webkit.org/show_bug.cgi?id=29287>
 http/tests/local/send-dragged-file.html
+http/tests/local/send-sliced-dragged-file.html
 
 # <https://bugs.webkit.org/show_bug.cgi?id=29289>
 plugins/destroy-during-npp-new.html
index ebca4f2..c2b7bf5 100644 (file)
@@ -1,3 +1,53 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+        
+        The following semantic is adopted per the discussions on public-webapps:
+        1) File.slice() does a synchronous IO to capture the current size and
+           modification time and cache them in the resulting Blob.
+        2) Subsequent Blob operations, like Blob.slice and Blob.size simply
+           use the cached values.
+        3) When the underlying file data are accessed, like in XHR.send(), the
+           UA will check the cached modification time against the current
+           modification time to determine if the file has been changed or not.
+           An error or exception will be thrown if needed.
+
+        Also add ENABLE_BLOB_SLICE feature define.
+
+        Test: http/tests/local/send-sliced-dragged-file.html
+
+        * Configurations/FeatureDefines.xcconfig:
+        * GNUmakefile.am:
+        * WebCore.pri:
+        * html/Blob.cpp:
+        (WebCore::Blob::Blob):
+        (WebCore::Blob::size):
+        (WebCore::Blob::slice):
+        * html/Blob.h:
+        (WebCore::Blob::start):
+        (WebCore::Blob::length):
+        (WebCore::Blob::modificationTime):
+        * html/Blob.idl:
+        * platform/network/FormData.cpp:
+        (WebCore::FormData::deepCopy):
+        (WebCore::FormData::appendFile):
+        (WebCore::FormData::appendFileRange):
+        * platform/network/FormData.h:
+        (WebCore::FormDataElement::FormDataElement):
+        (WebCore::operator==):
+        * platform/network/mac/FormDataStreamMac.mm:
+        (WebCore::advanceCurrentStream):
+        (WebCore::openNextStream):
+        (WebCore::formCreate):
+        (WebCore::formOpen):
+        (WebCore::formRead):
+        (WebCore::setHTTPBody):
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::send):
+
 2010-03-08  Daniel Bates  <dbates@rim.com>
 
         Reviewed by Simon Fraser.
index 4c4e193..eb96c27 100644 (file)
@@ -41,6 +41,7 @@ ENABLE_3D_RENDERING_1050 = ENABLE_3D_RENDERING;
 ENABLE_3D_RENDERING_1060 = ENABLE_3D_RENDERING;
 ENABLE_3D_RENDERING_1070 = ENABLE_3D_RENDERING;
 
+ENABLE_BLOB_SLICE = ENABLE_BLOB_SLICE;
 ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
 ENABLE_CLIENT_BASED_GEOLOCATION = ENABLE_CLIENT_BASED_GEOLOCATION;
 ENABLE_DATABASE = ENABLE_DATABASE;
@@ -74,4 +75,4 @@ ENABLE_XHTMLMP = ;
 ENABLE_XPATH = ENABLE_XPATH;
 ENABLE_XSLT = ENABLE_XSLT;
 
-FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
+FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
index 1439b09..e4d7770 100644 (file)
@@ -981,8 +981,8 @@ webcore_sources += \
        WebCore/history/HistoryItem.h \
        WebCore/history/PageCache.cpp \
        WebCore/history/PageCache.h \
-        WebCore/html/Blob.cpp \
-        WebCore/html/Blob.h \
+       WebCore/html/Blob.cpp \
+       WebCore/html/Blob.h \
        WebCore/html/canvas/CanvasContextAttributes.h \
        WebCore/html/canvas/CanvasGradient.cpp \
        WebCore/html/canvas/CanvasGradient.h \
@@ -3504,6 +3504,14 @@ else
 webcore_cppflags += -DENABLE_WEB_SOCKETS=0
 endif  # END ENABLE_WEB_SOCKETS
 
+# ---
+# Blob.slice support
+# ---
+if ENABLE_BLOB_SLICE
+FEATURE_DEFINES += ENABLE_BLOB_SLICE=1
+webcore_cppflags += -DENABLE_BLOB_SLICE=1
+endif  # END ENABLE_BLOB_SLICE
+
 
 DerivedSources/CSSPropertyNames.h: $(WEBCORE_CSS_PROPERTY_NAMES) $(WebCore)/css/makeprop.pl
        if sort $(WEBCORE_CSS_PROPERTY_NAMES) | uniq -d | grep -E '^[^#]'; then echo 'Duplicate value!'; exit 1; fi
index fc79f8d..88fef5e 100644 (file)
@@ -54,6 +54,7 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) {
 !contains(DEFINES, ENABLE_VIDEO=.): DEFINES += ENABLE_VIDEO=1
 !contains(DEFINES, ENABLE_RUBY=.): DEFINES += ENABLE_RUBY=1
 !contains(DEFINES, ENABLE_SANDBOX=.): DEFINES += ENABLE_SANDBOX=1
+!contains(DEFINES, ENABLE_BLOB_SLICE=.): DEFINES += ENABLE_BLOB_SLICE=0
 
 greaterThan(QT_MINOR_VERSION, 5) {
     !contains(DEFINES, ENABLE_3D_RENDERING=.): DEFINES += ENABLE_3D_RENDERING=1
index 0b677ea..be42442 100644 (file)
@@ -37,17 +37,77 @@ namespace WebCore {
 
 Blob::Blob(const String& path)
     : m_path(path)
+#if ENABLE(BLOB_SLICE)
+    , m_start(0)
+    , m_length(toEndOfFile)
+    , m_snapshotCaptured(false)
+    , m_snapshotSize(0)
+    , m_snapshotModificationTime(doNotCheckFileChange)
+#endif
 {
 }
 
+#if ENABLE(BLOB_SLICE)
+Blob::Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime)
+    : m_path(path)
+    , m_start(start)
+    , m_length(length)
+    , m_snapshotCaptured(true)
+    , m_snapshotSize(snapshotSize)
+    , m_snapshotModificationTime(snapshotModificationTime)
+{
+    ASSERT(start >= 0 && length >= 0 && start + length <= snapshotSize && snapshotModificationTime);
+}
+#endif
+
 unsigned long long Blob::size() const
 {
     // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
     // come up with an exception to throw if file size is not represetable.
+#if ENABLE(BLOB_SLICE)
+    if (m_snapshotCaptured)
+        return m_length;
+#endif
     long long size;
     if (!getFileSize(m_path, size))
         return 0;
     return static_cast<unsigned long long>(size);
 }
 
+#if ENABLE(BLOB_SLICE)
+PassRefPtr<Blob> Blob::slice(long long start, long long length) const
+{
+    // When we slice a file for the first time, we obtain a snapshot of the file by capturing its current size and modification time.
+    // The modification time will be used to verify if the file has been changed or not, when the underlying data are accessed.
+    long long snapshotSize;
+    double snapshotModificationTime;
+    if (m_snapshotCaptured) {
+        snapshotSize = m_snapshotSize;
+        snapshotModificationTime = m_snapshotModificationTime;
+    } else {
+        // If we fail to retrieve the size or modification time, probably due to that the file has been deleted, an empty blob will be returned.
+        time_t modificationTime;
+        if (!getFileSize(m_path, snapshotSize) || !getFileModificationTime(m_path, modificationTime)) {
+            snapshotSize = 0;
+            snapshotModificationTime = 0;
+        } else
+            snapshotModificationTime = modificationTime;
+    }
+
+    // Clamp the range if it exceeds the size limit.
+    if (start < 0)
+        start = 0;
+    if (length < 0)
+        length = 0;
+
+    if (start > snapshotSize) {
+        start = 0;
+        length = 0;
+    } else if (start + length > snapshotSize)
+        length = snapshotSize - start;
+
+    return adoptRef(new Blob(m_path, m_start + start, length, snapshotSize, snapshotModificationTime));
+}
+#endif
+
 } // namespace WebCore
index b910e8f..07e61af 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "ExceptionCode.h"
 #include "PlatformString.h"
+#include <time.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
@@ -40,6 +41,11 @@ namespace WebCore {
 
 class Blob : public RefCounted<Blob> {
 public:
+#if ENABLE(BLOB_SLICE)
+    static const int toEndOfFile = -1;
+    static const double doNotCheckFileChange = 0;
+#endif
+
     static PassRefPtr<Blob> create(const String& path)
     {
         return adoptRef(new Blob(path));
@@ -47,14 +53,45 @@ public:
 
     virtual ~Blob() { }
 
+#if ENABLE(BLOB_SLICE)
+    PassRefPtr<Blob> slice(long long start, long long length) const;
+#endif
+
     const String& path() const { return m_path; }
     unsigned long long size() const;
+#if ENABLE(BLOB_SLICE)
+    long long start() const { return m_start; }
+    long long length() const { return m_length; }
+    double modificationTime() const { return m_snapshotModificationTime; }
+#endif
 
 protected:
     Blob(const String& path);
 
 private:
+#if ENABLE(BLOB_SLICE)
+    Blob(const String& path, long long start, long long length, long long snapshotSize, double snapshotModificationTime);
+#endif
+
+    // The underlying path of the file-based blob. 
     String m_path;
+
+#if ENABLE(BLOB_SLICE)
+    // The starting position of the file-based blob.
+    long long m_start;
+
+    // The length of the file-based blob. The value of -1 means to the end of the file.
+    long long m_length;
+
+    // A flag to tell if a snapshot has been captured.
+    bool m_snapshotCaptured;
+
+    // The size of the file when a snapshot is captured. It can be 0 if the file is empty.
+    long long m_snapshotSize;
+
+    // The last modification time of the file when a snapshot is captured. The value of 0 also means that the snapshot is not captured.
+    double m_snapshotModificationTime;
+#endif
 };
 
 } // namespace WebCore
index 573be35..8db6064 100644 (file)
@@ -32,6 +32,10 @@ module html {
 
     interface Blob {
         readonly attribute unsigned long long size;
+        
+#if defined(ENABLE_BLOB_SLICE) && ENABLE_BLOB_SLICE
+        Blob slice(in long long start, in long long length);
+#endif
     };
 
 }
index af3b7f0..a8456b2 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "FormData.h"
 
+#include "Blob.h"
 #include "CString.h"
 #include "ChromeClient.h"
 #include "FileSystem.h"
@@ -108,7 +109,11 @@ PassRefPtr<FormData> FormData::deepCopy() const
             formData->m_elements.append(FormDataElement(e.m_data));
             break;
         case FormDataElement::encodedFile:
+#if ENABLE(BLOB_SLICE)
+            formData->m_elements.append(FormDataElement(e.m_filename, e.m_fileStart, e.m_fileLength, e.m_expectedFileModificationTime, e.m_shouldGenerateFile));
+#else
             formData->m_elements.append(FormDataElement(e.m_filename, e.m_shouldGenerateFile));
+#endif
             break;
         }
     }
@@ -127,9 +132,20 @@ void FormData::appendData(const void* data, size_t size)
 
 void FormData::appendFile(const String& filename, bool shouldGenerateFile)
 {
+#if ENABLE(BLOB_SLICE)
+    m_elements.append(FormDataElement(filename, 0, Blob::toEndOfFile, Blob::doNotCheckFileChange, shouldGenerateFile));
+#else
     m_elements.append(FormDataElement(filename, shouldGenerateFile));
+#endif
 }
 
+#if ENABLE(BLOB_SLICE)
+void FormData::appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile)
+{
+    m_elements.append(FormDataElement(filename, start, length, expectedModificationTime, shouldGenerateFile));
+}
+#endif
+
 void FormData::flatten(Vector<char>& data) const
 {
     // Concatenate all the byte arrays, but omit any files.
index 7278f2e..48e5154 100644 (file)
@@ -32,11 +32,20 @@ class FormDataElement {
 public:
     FormDataElement() : m_type(data) { }
     FormDataElement(const Vector<char>& array) : m_type(data), m_data(array) { }
+#if ENABLE(BLOB_SLICE)
+    FormDataElement(const String& filename, long long fileStart, long long fileLength, double expectedFileModificationTime, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_fileStart(fileStart), m_fileLength(fileLength), m_expectedFileModificationTime(expectedFileModificationTime), m_shouldGenerateFile(shouldGenerateFile) { }
+#else
     FormDataElement(const String& filename, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_shouldGenerateFile(shouldGenerateFile) { }
+#endif
 
     enum { data, encodedFile } m_type;
     Vector<char> m_data;
     String m_filename;
+#if ENABLE(BLOB_SLICE)
+    long long m_fileStart;
+    long long m_fileLength;
+    double m_expectedFileModificationTime;
+#endif
     String m_generatedFilename;
     bool m_shouldGenerateFile;
 };
@@ -50,7 +59,11 @@ inline bool operator==(const FormDataElement& a, const FormDataElement& b)
         return false;
     if (a.m_data != b.m_data)
         return false;
+#if ENABLE(BLOB_SLICE)
+    if (a.m_filename != b.m_filename || a.m_fileStart != b.m_fileStart || a.m_fileLength != b.m_fileLength || a.m_expectedFileModificationTime != b.m_expectedFileModificationTime)
+#else
     if (a.m_filename != b.m_filename)
+#endif
         return false;
 
     return true;
@@ -73,6 +86,9 @@ public:
     
     void appendData(const void* data, size_t);
     void appendFile(const String& filename, bool shouldGenerateFile = false);
+#if ENABLE(BLOB_SLICE)
+    void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false);
+#endif
 
     void flatten(Vector<char>&) const; // omits files
     String flattenToString() const; // omits files
index 8aa9a6d..5e8c3ff 100644 (file)
@@ -31,6 +31,7 @@
 #import "config.h"
 #import "FormDataStreamMac.h"
 
+#import "Blob.h"
 #import "CString.h"
 #import "FileSystem.h"
 #import "FormData.h"
@@ -125,6 +126,9 @@ struct FormStreamFields {
     SchedulePairHashSet scheduledRunLoopPairs;
     Vector<FormDataElement> remainingElements; // in reverse order
     CFReadStreamRef currentStream;
+#if ENABLE(BLOB_SLICE)
+    long long currentStreamRangeLength;
+#endif
     char* currentData;
     CFReadStreamRef formStream;
     unsigned long long streamLength;
@@ -145,12 +149,13 @@ static void closeCurrentStream(FormStreamFields *form)
     }
 }
 
-static void advanceCurrentStream(FormStreamFields *form)
+// Return false if we cannot advance the stream. Currently the only possible failure is that the underlying file has been changed since File.slice. 
+static bool advanceCurrentStream(FormStreamFields* form)
 {
     closeCurrentStream(form);
 
     if (form->remainingElements.isEmpty())
-        return;
+        return true;
 
     // Create the new stream.
     FormDataElement& nextInput = form->remainingElements.last();
@@ -160,10 +165,26 @@ static void advanceCurrentStream(FormStreamFields *form)
         form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
         form->currentData = data;
     } else {
+#if ENABLE(BLOB_SLICE)
+        // Check if the file has been changed or not if required.
+        if (nextInput.m_expectedFileModificationTime != Blob::doNotCheckFileChange) {
+            time_t fileModificationTime;
+            if (!getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime))
+                return false;
+        }
+#endif
+
         const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
         RetainPtr<CFStringRef> filename(AdoptCF, path.createCFString());
         RetainPtr<CFURLRef> fileURL(AdoptCF, CFURLCreateWithFileSystemPath(0, filename.get(), kCFURLPOSIXPathStyle, FALSE));
         form->currentStream = CFReadStreamCreateWithFile(0, fileURL.get());
+#if ENABLE(BLOB_SLICE)
+        if (nextInput.m_fileStart > 0) {
+            CFNumberRef position = CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart);
+            CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position);
+        }
+        form->currentStreamRangeLength = nextInput.m_fileLength;
+#endif
     }
     form->remainingElements.removeLast();
 
@@ -176,16 +197,20 @@ static void advanceCurrentStream(FormStreamFields *form)
     SchedulePairHashSet::iterator end = form->scheduledRunLoopPairs.end();
     for (SchedulePairHashSet::iterator it = form->scheduledRunLoopPairs.begin(); it != end; ++it)
         CFReadStreamScheduleWithRunLoop(form->currentStream, (*it)->runLoop(), (*it)->mode());
+
+    return true;
 }
 
-static void openNextStream(FormStreamFields* form)
+static bool openNextStream(FormStreamFields* form)
 {
     // Skip over any streams we can't open.
-    // For some purposes we might want to return an error, but the current NSURLConnection
-    // can't really do anything useful with an error at this point, so this is better.
-    advanceCurrentStream(form);
-    while (form->currentStream && !CFReadStreamOpen(form->currentStream))
-        advanceCurrentStream(form);
+    if (!advanceCurrentStream(form))
+        return false;
+    while (form->currentStream && !CFReadStreamOpen(form->currentStream)) {
+        if (!advanceCurrentStream(form))
+            return false;
+    }
+    return true;
 }
 
 static void* formCreate(CFReadStreamRef stream, void* context)
@@ -194,6 +219,9 @@ static void* formCreate(CFReadStreamRef stream, void* context)
 
     FormStreamFields* newInfo = new FormStreamFields;
     newInfo->currentStream = NULL;
+#if ENABLE(BLOB_SLICE)
+    newInfo->currentStreamRangeLength = Blob::toEndOfFile;
+#endif
     newInfo->currentData = 0;
     newInfo->formStream = stream; // Don't retain. That would create a reference cycle.
     newInfo->streamLength = formContext->streamLength;
@@ -226,11 +254,11 @@ static Boolean formOpen(CFReadStreamRef, CFStreamError* error, Boolean* openComp
 {
     FormStreamFields* form = static_cast<FormStreamFields*>(context);
 
-    openNextStream(form);
+    bool opened = openNextStream(form);
 
-    *openComplete = TRUE;
-    error->error = 0;
-    return TRUE;
+    *openComplete = opened;
+    error->error = opened ? 0 : fnfErr;
+    return opened;
 }
 
 static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLength, CFStreamError* error, Boolean* atEOF, void* context)
@@ -238,7 +266,12 @@ static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLen
     FormStreamFields* form = static_cast<FormStreamFields*>(context);
 
     while (form->currentStream) {
-        CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bufferLength);
+        CFIndex bytesToRead = bufferLength;
+#if ENABLE(BLOB_SLICE)
+        if (form->currentStreamRangeLength != Blob::toEndOfFile && form->currentStreamRangeLength < bytesToRead)
+            bytesToRead = static_cast<CFIndex>(form->currentStreamRangeLength);
+#endif
+        CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bytesToRead);
         if (bytesRead < 0) {
             *error = CFReadStreamGetError(form->currentStream);
             return -1;
@@ -247,6 +280,10 @@ static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLen
             error->error = 0;
             *atEOF = FALSE;
             form->bytesSent += bytesRead;
+#if ENABLE(BLOB_SLICE)
+            if (form->currentStreamRangeLength != Blob::toEndOfFile)
+                form->currentStreamRangeLength -= bytesRead;
+#endif
 
             if (!ResourceHandle::didSendBodyDataDelegateExists()) {
                 // FIXME: Figure out how to only do this when a ResourceHandleClient is available.
@@ -359,6 +396,13 @@ void setHTTPBody(NSMutableURLRequest *request, PassRefPtr<FormData> formData)
         if (element.m_type == FormDataElement::data)
             length += element.m_data.size();
         else {
+#if ENABLE(BLOB_SLICE)
+            // 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.
+            if (element.m_fileLength != Blob::toEndOfFile) {
+                length += element.m_fileLength;
+                continue;
+            }
+#endif
             long long fileSize;
             if (getFileSize(element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename, fileSize))
                 length += fileSize;
index 0e04ccb..abdb58a 100644 (file)
@@ -449,7 +449,11 @@ void XMLHttpRequest::send(Blob* body, ExceptionCode& ec)
         // FIXME: Should we set a Content-Type if one is not set.
         // FIXME: add support for uploading bundles.
         m_requestEntityBody = FormData::create();
+#if ENABLE(BLOB_SLICE)
+        m_requestEntityBody->appendFileRange(body->path(), body->start(), body->length(), body->modificationTime());
+#else
         m_requestEntityBody->appendFile(body->path(), false);
+#endif
     }
 
     createRequest(ec);
index c507dda..0011427 100644 (file)
@@ -1,3 +1,14 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+
+        Add ENABLE_BLOB_SLICE feature define.
+
+        * features.gypi:
+
 2010-03-08  Eric Uhrhane  <ericu@chromium.org>
 
         Reviewed by David Levin.
index bfc4966..a40dc59 100644 (file)
@@ -40,6 +40,7 @@
       # features_override.gypi inline documentation for more details.
       'feature_defines%': [
         'ENABLE_3D_CANVAS=0',
+        'ENABLE_BLOB_SLICE=0',
         'ENABLE_CHANNEL_MESSAGING=1',
         'ENABLE_DATABASE=1',
         'ENABLE_DATAGRID=0',
index b33cc4f..fbb55d2 100644 (file)
@@ -1,3 +1,14 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+
+        Add ENABLE_BLOB_SLICE feature define.
+
+        * Configurations/FeatureDefines.xcconfig:
+
 2010-03-08  Eric Uhrhane  <ericu@chromium.org>
 
         Reviewed by David Levin.
index 4c4e193..eb96c27 100644 (file)
@@ -41,6 +41,7 @@ ENABLE_3D_RENDERING_1050 = ENABLE_3D_RENDERING;
 ENABLE_3D_RENDERING_1060 = ENABLE_3D_RENDERING;
 ENABLE_3D_RENDERING_1070 = ENABLE_3D_RENDERING;
 
+ENABLE_BLOB_SLICE = ENABLE_BLOB_SLICE;
 ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
 ENABLE_CLIENT_BASED_GEOLOCATION = ENABLE_CLIENT_BASED_GEOLOCATION;
 ENABLE_DATABASE = ENABLE_DATABASE;
@@ -74,4 +75,4 @@ ENABLE_XHTMLMP = ;
 ENABLE_XPATH = ENABLE_XPATH;
 ENABLE_XSLT = ENABLE_XSLT;
 
-FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
+FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
index 62053d1..9bcc7c2 100644 (file)
@@ -1,3 +1,15 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+
+        Add ENABLE_BLOB_SLICE feature define.
+
+        * win/tools/vsprops/FeatureDefines.vsprops:
+        * win/tools/vsprops/FeatureDefinesCairo.vsprops:
+
 2010-02-19  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by David Levin.
index f7a754d..45dacbc 100644 (file)
@@ -9,7 +9,7 @@
        >
   <Tool
                Name="VCCLCompilerTool"
-               PreprocessorDefinitions="$(ENABLE_3D_CANVAS);$(ENABLE_3D_RENDERING);$(ENABLE_CHANNEL_MESSAGING);$(ENABLE_CLIENT_BASED_GEOLOCATION);$(ENABLE_DATABASE);$(ENABLE_DATAGRID);$(ENABLE_DATALIST);$(ENABLE_DOM_STORAGE);$(ENABLE_EVENTSOURCE);$(ENABLE_FILTERS);$(ENABLE_GEOLOCATION);$(ENABLE_ICONDATABASE);$(ENABLE_INDEXED_DATABASE);$(ENABLE_JAVASCRIPT_DEBUGGER);$(ENABLE_MATHML);$(ENABLE_NOTIFICATIONS);$(ENABLE_OFFLINE_WEB_APPLICATIONS);$(ENABLE_RUBY);$(ENABLE_SANDBOX);$(ENABLE_SHARED_WORKERS);$(ENABLE_SVG);$(ENABLE_SVG_ANIMATION);$(ENABLE_SVG_AS_IMAGE);$(ENABLE_SVG_DOM_OBJC_BINDINGS);$(ENABLE_SVG_FONTS);$(ENABLE_SVG_FOREIGN_OBJECT);$(ENABLE_SVG_USE);$(ENABLE_VIDEO);$(ENABLE_WEB_SOCKETS);$(ENABLE_WML);$(ENABLE_WORKERS);$(ENABLE_XHTMLMP);$(ENABLE_XPATH);$(ENABLE_XSLT)"
+               PreprocessorDefinitions="$(ENABLE_3D_CANVAS);$(ENABLE_3D_RENDERING);$(ENABLE_BLOB_SLICE);$(ENABLE_CHANNEL_MESSAGING);$(ENABLE_CLIENT_BASED_GEOLOCATION);$(ENABLE_DATABASE);$(ENABLE_DATAGRID);$(ENABLE_DATALIST);$(ENABLE_DOM_STORAGE);$(ENABLE_EVENTSOURCE);$(ENABLE_FILTERS);$(ENABLE_GEOLOCATION);$(ENABLE_ICONDATABASE);$(ENABLE_INDEXED_DATABASE);$(ENABLE_JAVASCRIPT_DEBUGGER);$(ENABLE_MATHML);$(ENABLE_NOTIFICATIONS);$(ENABLE_OFFLINE_WEB_APPLICATIONS);$(ENABLE_RUBY);$(ENABLE_SANDBOX);$(ENABLE_SHARED_WORKERS);$(ENABLE_SVG);$(ENABLE_SVG_ANIMATION);$(ENABLE_SVG_AS_IMAGE);$(ENABLE_SVG_DOM_OBJC_BINDINGS);$(ENABLE_SVG_FONTS);$(ENABLE_SVG_FOREIGN_OBJECT);$(ENABLE_SVG_USE);$(ENABLE_VIDEO);$(ENABLE_WEB_SOCKETS);$(ENABLE_WML);$(ENABLE_WORKERS);$(ENABLE_XHTMLMP);$(ENABLE_XPATH);$(ENABLE_XSLT)"
        />
   <UserMacro
                Name="ENABLE_3D_CANVAS"
                PerformEnvironmentSet="true"
        />
   <UserMacro
+               Name="ENABLE_BLOB_SLICE"
+               Value=""
+               PerformEnvironmentSet="true"
+       />
+  <UserMacro
                Name="ENABLE_CHANNEL_MESSAGING"
                Value="ENABLE_CHANNEL_MESSAGING"
                PerformEnvironmentSet="true"
index 1c16a9b..e737ffa 100644 (file)
@@ -9,7 +9,7 @@
        >
   <Tool
                Name="VCCLCompilerTool"
-               PreprocessorDefinitions="$(ENABLE_3D_CANVAS);$(ENABLE_3D_RENDERING);$(ENABLE_CHANNEL_MESSAGING);$(ENABLE_CLIENT_BASED_GEOLOCATION);$(ENABLE_DATABASE);$(ENABLE_DATAGRID);$(ENABLE_DATALIST);$(ENABLE_DOM_STORAGE);$(ENABLE_EVENTSOURCE);$(ENABLE_FILTERS);$(ENABLE_GEOLOCATION);$(ENABLE_ICONDATABASE);$(ENABLE_INDEXED_DATABASE);$(ENABLE_JAVASCRIPT_DEBUGGER);$(ENABLE_MATHML);$(ENABLE_NOTIFICATIONS);$(ENABLE_OFFLINE_WEB_APPLICATIONS);$(ENABLE_SHARED_WORKERS);$(ENABLE_SVG);$(ENABLE_SVG_ANIMATION);$(ENABLE_SVG_AS_IMAGE);$(ENABLE_SVG_DOM_OBJC_BINDINGS);$(ENABLE_SVG_FONTS);$(ENABLE_SVG_FOREIGN_OBJECT);$(ENABLE_SVG_USE);$(ENABLE_VIDEO);$(ENABLE_WEB_SOCKETS);$(ENABLE_WML);$(ENABLE_WORKERS);$(ENABLE_XHTMLMP);$(ENABLE_XPATH);$(ENABLE_XSLT)"
+               PreprocessorDefinitions="$(ENABLE_3D_CANVAS);$(ENABLE_3D_RENDERING);$(ENABLE_BLOB_SLICE);$(ENABLE_CHANNEL_MESSAGING);$(ENABLE_CLIENT_BASED_GEOLOCATION);$(ENABLE_DATABASE);$(ENABLE_DATAGRID);$(ENABLE_DATALIST);$(ENABLE_DOM_STORAGE);$(ENABLE_EVENTSOURCE);$(ENABLE_FILTERS);$(ENABLE_GEOLOCATION);$(ENABLE_ICONDATABASE);$(ENABLE_INDEXED_DATABASE);$(ENABLE_JAVASCRIPT_DEBUGGER);$(ENABLE_MATHML);$(ENABLE_NOTIFICATIONS);$(ENABLE_OFFLINE_WEB_APPLICATIONS);$(ENABLE_SHARED_WORKERS);$(ENABLE_SVG);$(ENABLE_SVG_ANIMATION);$(ENABLE_SVG_AS_IMAGE);$(ENABLE_SVG_DOM_OBJC_BINDINGS);$(ENABLE_SVG_FONTS);$(ENABLE_SVG_FOREIGN_OBJECT);$(ENABLE_SVG_USE);$(ENABLE_VIDEO);$(ENABLE_WEB_SOCKETS);$(ENABLE_WML);$(ENABLE_WORKERS);$(ENABLE_XHTMLMP);$(ENABLE_XPATH);$(ENABLE_XSLT)"
        />
   <UserMacro
                Name="ENABLE_3D_CANVAS"
                PerformEnvironmentSet="true"
        />
   <UserMacro
+               Name="ENABLE_BLOB_SLICE"
+               Value=""
+               PerformEnvironmentSet="true"
+       />
+  <UserMacro
                Name="ENABLE_CHANNEL_MESSAGING"
                Value="ENABLE_CHANNEL_MESSAGING"
                PerformEnvironmentSet="true"
index 0f36cd1..060aa0d 100644 (file)
@@ -1,3 +1,15 @@
+2010-03-08  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dmitry Titov.
+
+        Blob.slice support.
+        https://bugs.webkit.org/show_bug.cgi?id=32993
+
+        Add ENABLE_BLOB_SLICE feature define and  flag for build-webkit. It is
+        currently only turned on for Mac.
+
+        * Scripts/build-webkit:
+
 2010-03-08  Gustavo Noronha Silva  <gns@gnome.org>
 
         No review, rolling out r55662.
index ed5e368..413c971 100755 (executable)
@@ -56,7 +56,7 @@ my ($threeDCanvasSupport, $threeDRenderingSupport, $channelMessagingSupport, $cl
     $javaScriptDebuggerSupport, $mathmlSupport, $offlineWebApplicationSupport, $rubySupport, $sandboxSupport, $sharedWorkersSupport,
     $svgSupport, $svgAnimationSupport, $svgAsImageSupport, $svgDOMObjCBindingsSupport, $svgFontsSupport,
     $svgForeignObjectSupport, $svgUseSupport, $videoSupport, $webSocketsSupport, $wmlSupport, $wcssSupport, $xhtmlmpSupport, $workersSupport,
-    $xpathSupport, $xsltSupport, $coverageSupport, $notificationsSupport);
+    $xpathSupport, $xsltSupport, $coverageSupport, $notificationsSupport, $blobSliceSupport);
 
 my @features = (
     { option => "3d-canvas", desc => "Toggle 3D canvas support",
@@ -65,6 +65,9 @@ my @features = (
     { option => "3d-rendering", desc => "Toggle 3D rendering support",
       define => "ENABLE_3D_RENDERING", default => (isAppleMacWebKit() && !isTiger()), value => \$threeDRenderingSupport },
 
+    { option => "blob-slice", desc => "Toggle Blob.slice support",
+      define => "ENABLE_BLOB_SLICE", default => (isAppleMacWebKit()), value => \$blobSliceSupport },
+
     { option => "channel-messaging", desc => "Toggle MessageChannel and MessagePort support",
       define => "ENABLE_CHANNEL_MESSAGING", default => 1, value => \$channelMessagingSupport },
 
index 4e33249..f0f11bf 100644 (file)
@@ -553,6 +553,14 @@ AC_ARG_ENABLE(web_sockets,
               [],[enable_web_sockets="no"])
 AC_MSG_RESULT([$enable_web_sockets])
 
+# check whether to enable Blob.slice support
+AC_MSG_CHECKING([whether to enable Blob.slice support])
+AC_ARG_ENABLE(blob_slice,
+              AC_HELP_STRING([--enable-blob-slice],
+                             [enable support for Blob.slice [default=no]]),
+              [],[enable_blob_slice="no"])
+AC_MSG_RESULT([$enable_blob_slice])
+
 # check whether to enable code coverage
 AC_MSG_CHECKING([whether to enable code coverage support])
 AC_ARG_ENABLE(coverage,
@@ -776,6 +784,7 @@ AM_CONDITIONAL([USE_PANGO], [test "$with_font_backend" = "pango"])
 # WebKit feature conditionals
 AM_CONDITIONAL([ENABLE_DEBUG],[test "$enable_debug" = "yes"])
 AM_CONDITIONAL([ENABLE_3D_TRANSFORMS],[test "$enable_3D_transforms" = "yes"])
+AM_CONDITIONAL([ENABLE_BLOB_SLICE],[test "$enable_blob_slice" = "yes"])
 AM_CONDITIONAL([ENABLE_CHANNEL_MESSAGING],[test "$enable_channel_messaging" = "yes"])
 AM_CONDITIONAL([ENABLE_JAVASCRIPT_DEBUGGER],[test "$enable_javascript_debugger" = "yes"])
 AM_CONDITIONAL([ENABLE_OFFLINE_WEB_APPLICATIONS],[test "$enable_offline_web_applications" = "yes"])
@@ -838,6 +847,7 @@ Build configuration:
  Optimized memory allocator                               : $enable_fast_malloc
 Features:
  3D Transforms                                            : $enable_3D_transforms
+ Blob.slice support                                       : $enable_blob_slice
  JIT compilation                                          : $enable_jit
  Filters support                                          : $enable_filters
  Geolocation support                                      : $enable_geolocation