.: 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 a2803926b092f6bd38688fd0f050365b15aa6b01..38163b0a72c0cb161e1519794aa7d686ba88b6bb 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 20c4846890937ce3fc1d26dd77eb67af577f57b4..b9444ea6046a1920d40a664ccf95dbbb76e2ca7d 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 4c4e193cd0fc24bb07773c9be84fc5a6cbc504b8..eb96c272030edf4c89fa86878875dede3684afdc 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 0818a3e893b72d08be707c799be15a54ebe9a002..219bcfd59527bb94a0fe0cb773b371ad856f0e7f 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 0e51907b0e2bee063334bda4a8b4e626c9865d73..68ba559983c070e7fc6b1a3a9957d8726f955545 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 03e64787ea5d03512639b40ba356337fd6bf18c6..a5e00b6d2d180572b646fac8fe675250941a9941 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 5ab2f8a4323abafb10abb68657d9d39f1a775057..6a537b5b367880eac21e3c0f0a382de7a19bd30a 100644 (file)
@@ -1 +1 @@
-Hello
\ No newline at end of file
+1234567890
\ No newline at end of file
index bed407870e25d770be8dc4cbc1a478959c797c48..efc11246d5bcf8f9b496c1923cf8a420de635e28 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 3f2210a8357978f68939295bf8dcbf718b8c7710..f5280f4cdb0d9257fa6d86cc9948555b6ccb8ee3 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 67232181d37e4d44efb7afb917f16ff574abdf5d..88918016b24ce6605f23296a98d2b97fdb291e6d 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 0df3ab64004e35c1a235bf1e861b9e0ead378982..184f476bad0266ef8c129153663fa97562ce5ada 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 4047618171e53ffdb991d23002b4dd444941fc1d..90f9f70ca4847f563307b39adbd8b3f188b3aa1d 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 ebca4f260710d17a068d7207cab35dc1db69fe0c..c2b7bf581a414ed9549015a9da9417131c0c9cf4 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 4c4e193cd0fc24bb07773c9be84fc5a6cbc504b8..eb96c272030edf4c89fa86878875dede3684afdc 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 1439b09036303d0df09e915ee2c0d8b0ca382708..e4d7770c5eb98d3367af397307e448e4ce1b8232 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 fc79f8d00d10a755fedf9e7a6d2f8f00c0ccc9df..88fef5eb93d44213907882dd0c0c8418ed4c631f 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 0b677eac0f52ef4bacde1042ae997d6e90d54f3b..be424427559a00bbf4161337cecd5eadf18dc2e6 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 b910e8fad7f0424c7e818b1b7bd0f143ef58e91d..07e61aff73b134719c55f0830d1b3d876c5eca4f 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 573be3566d478b2c4e7475b6a8b1b2f7867700e6..8db6064a875e4dae6fb859a3232b612f7785ffcb 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 af3b7f0782c2a05d62b0eec252ae48253a5d6056..a8456b22a835d1923ffc6e0bdbcab2e949d308a1 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 7278f2eee51fc56a30b296a2a6dcf48b5ec9b3e3..48e5154a3892cd25327e0bea96e53121d797b549 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 8aa9a6df6c8be7876a5fefd478a94d8519d00dce..5e8c3ff4a18f5b3199bf8f4ea72cb2fc6049d828 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 0e04ccb33bc4d7937a5313b35b558ca7530ce4ee..abdb58a08febaf88dbb78e670031f2675c69fd81 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 c507ddaa3990179f9839207b167bec038196b8eb..0011427ae960b9223b74bcf5fd51a3aa36ac2b90 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 bfc4966ebb868092de6db9cfbd0ab8248230e4ea..a40dc594f5d300da0fc847bdbf108456b4f3e903 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 b33cc4fa5b22031cf9dd80a49d21aad8b62b4ef7..fbb55d2893c738a3cfa6f737ab5508439923afc3 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 4c4e193cd0fc24bb07773c9be84fc5a6cbc504b8..eb96c272030edf4c89fa86878875dede3684afdc 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 62053d148bd82655b15cb4a0cb65301885752bb1..9bcc7c23cdda9bd6505e8a638d1c83775537cb1f 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 f7a754d8f4102554a96f7e007b0f71b3326c88b7..45dacbcff93ab5e55a8511d3716bce3835635b1c 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"
                Value=""
                PerformEnvironmentSet="true"
        />
+  <UserMacro
+               Name="ENABLE_BLOB_SLICE"
+               Value=""
+               PerformEnvironmentSet="true"
+       />
   <UserMacro
                Name="ENABLE_CHANNEL_MESSAGING"
                Value="ENABLE_CHANNEL_MESSAGING"
index 1c16a9b1e2beddb68f99f467fc6b00eb8c353c9a..e737ffaf7433b0d3688594135d5dbe5c141f7921 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"
                Value=""
                PerformEnvironmentSet="true"
        />
+  <UserMacro
+               Name="ENABLE_BLOB_SLICE"
+               Value=""
+               PerformEnvironmentSet="true"
+       />
   <UserMacro
                Name="ENABLE_CHANNEL_MESSAGING"
                Value="ENABLE_CHANNEL_MESSAGING"
index 0f36cd19731ce74fffab9cf173678d7f1ea7dbbc..060aa0d49263e6976f43ce2950db9f33ab909e72 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 ed5e36854ebcb9fb37db6b36a4377ccb05e1cc50..413c971f68ef91744a86e38a2bd5a6ab175fe1c4 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 4e33249517d0bdaa016884a43045d9cdeadb5950..f0f11bfe49370a0de2e117dfffe13d7302891686 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