Back it all out on this CLOSED TREE. a=mfbt

This commit is contained in:
Kyle Huey 2011-05-20 17:00:46 -07:00
Родитель 796570d4fa 18e6d04d41
Коммит 3e8fcba590
11 изменённых файлов: 289 добавлений и 839 удалений

Просмотреть файл

@ -40,7 +40,6 @@
#define nsDOMFile_h__
#include "nsICharsetDetectionObserver.h"
#include "nsIFile.h"
#include "nsIDOMFile.h"
#include "nsIDOMFileList.h"
#include "nsIDOMFileError.h"
@ -57,12 +56,9 @@
class nsIFile;
class nsIInputStream;
class nsIClassInfo;
class nsIBlobBuilder;
nsresult NS_NewBlobBuilder(nsISupports* *aSupports);
void ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd);
class nsDOMFile : public nsIDOMFile,
public nsIDOMBlob_MOZILLA_2_0_BRANCH,
public nsIXHRSendable,
public nsICharsetDetectionObserver,
public nsIJSNativeInitializer
@ -71,6 +67,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMBLOB
NS_DECL_NSIDOMFILE
NS_DECL_NSIDOMBLOB_MOZILLA_2_0_BRANCH
NS_DECL_NSIXHRSENDABLE
nsDOMFile(nsIFile *aFile, const nsAString& aContentType)

Просмотреть файл

@ -37,33 +37,37 @@
#include "domstubs.idl"
%{C++
#include "jsapi.h"
%}
interface nsIDOMFileError;
interface nsIInputStream;
interface nsIURI;
interface nsIPrincipal;
interface nsIDOMBlob;
[scriptable, uuid(d5237f31-443a-460b-9e42-449a135346f0)]
[scriptable, uuid(5822776a-049c-4de7-adb6-dd9efc39d082)]
interface nsIDOMBlob : nsISupports
{
readonly attribute unsigned long long size;
readonly attribute DOMString type;
[noscript] nsIDOMBlob slice(in unsigned long long start,
in unsigned long long length,
[optional] in DOMString contentType);
[noscript] readonly attribute nsIInputStream internalStream;
// The caller is responsible for releasing the internalUrl from the
// moz-filedata: protocol handler
[noscript] DOMString getInternalUrl(in nsIPrincipal principal);
};
[scriptable, uuid(cb5b4191-a555-4e57-b8d2-88091184b59f)]
interface nsIDOMBlob_MOZILLA_2_0_BRANCH : nsISupports
{
[optional_argc] nsIDOMBlob mozSlice(in long long start,
[optional] in long long end,
[optional] in DOMString contentType);
};
[scriptable, uuid(91c9ebd9-2a4a-4a38-9412-ef492a2799be)]
[scriptable, uuid(ae1405b0-e411-481e-9606-b29ec7982687)]
interface nsIDOMFile : nsIDOMBlob
{
readonly attribute DOMString name;
@ -80,10 +84,3 @@ interface nsIDOMFile : nsIDOMBlob
DOMString getAsDataURL(); // raises(FileException) on retrieval
DOMString getAsBinary(); // raises(FileException) on retrieval
};
[scriptable, uuid(c4a77171-039b-4f84-97f9-820fb51626af)]
interface nsIDOMBlobBuilder : nsISupports
{
nsIDOMBlob getBlob([optional] in DOMString contentType);
[implicit_jscontext] void append(in jsval data);
};

Просмотреть файл

@ -92,7 +92,6 @@ CPPSRCS = \
nsDataDocumentContentPolicy.cpp \
nsDOMAttribute.cpp \
nsDOMAttributeMap.cpp \
nsDOMBlobBuilder.cpp \
nsDOMDocumentType.cpp \
nsDOMEventTargetWrapperCache.cpp \
nsDOMFile.cpp \

Просмотреть файл

@ -1,399 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla File API.
*
* The Initial Developer of the Original Code is
* Kyle Huey <me@kylehuey.com>
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "jstypedarray.h"
#include "nsAutoPtr.h"
#include "nsDOMClassInfo.h"
#include "nsDOMFile.h"
#include "nsIMultiplexInputStream.h"
#include "nsStringStream.h"
#include "nsTArray.h"
#include "nsJSUtils.h"
#include "nsContentUtils.h"
#include "CheckedInt.h"
// XXXkhuey shamelessly stolen from VideoUtils.h. We should patch NSPR.
#define PR_INT64_MAX (~((PRInt64)(1) << 63))
#define PR_INT64_MIN (-PR_INT64_MAX - 1)
using namespace mozilla;
class nsDOMMultipartBlob : public nsDOMFile
{
public:
nsDOMMultipartBlob(nsTArray<nsCOMPtr<nsIDOMBlob> > aBlobs,
const nsAString& aContentType)
: nsDOMFile(nsnull, aContentType),
mBlobs(aBlobs)
{
mIsFullFile = false;
mStart = 0;
mLength = 0;
}
NS_IMETHOD GetSize(PRUint64*);
NS_IMETHOD GetInternalStream(nsIInputStream**);
NS_IMETHOD MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType, PRUint8 optional_argc,
nsIDOMBlob **aBlob);
protected:
nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
};
NS_IMETHODIMP
nsDOMMultipartBlob::GetSize(PRUint64* aLength)
{
nsresult rv;
*aLength = 0;
if (mLength) {
*aLength = mLength;
return NS_OK;
}
CheckedUint64 length = 0;
PRUint32 i;
PRUint32 len = mBlobs.Length();
for (i = 0; i < len; i++) {
nsIDOMBlob* blob = mBlobs.ElementAt(i).get();
PRUint64 l = 0;
rv = blob->GetSize(&l);
NS_ENSURE_SUCCESS(rv, rv);
length += l;
}
if (!length.valid())
return NS_ERROR_FAILURE;
mLength = length.value();
*aLength = mLength;
return NS_OK;
}
NS_IMETHODIMP
nsDOMMultipartBlob::GetInternalStream(nsIInputStream** aStream)
{
nsresult rv;
*aStream = nsnull;
nsCOMPtr<nsIMultiplexInputStream> stream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE);
PRUint32 i;
for (i = 0; i < mBlobs.Length(); i++) {
nsCOMPtr<nsIInputStream> scratchStream;
nsIDOMBlob* blob = mBlobs.ElementAt(i).get();
rv = blob->GetInternalStream(getter_AddRefs(scratchStream));
NS_ENSURE_SUCCESS(rv, rv);
rv = stream->AppendStream(scratchStream);
NS_ENSURE_SUCCESS(rv, rv);
}
return CallQueryInterface(stream, aStream);
}
NS_IMETHODIMP
nsDOMMultipartBlob::MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType,
PRUint8 optional_argc,
nsIDOMBlob **aBlob)
{
nsresult rv;
*aBlob = nsnull;
// Truncate aStart and aEnd so that we stay within this file.
PRUint64 thisLength;
rv = GetSize(&thisLength);
NS_ENSURE_SUCCESS(rv, rv);
if (!optional_argc) {
aEnd = (PRInt64)thisLength;
}
ParseSize((PRInt64)thisLength, aStart, aEnd);
// If we clamped to nothing we create an empty blob
nsTArray<nsCOMPtr<nsIDOMBlob> > blobs;
PRInt64 length = aEnd - aStart;
PRUint64 finalLength = length;
PRUint64 skipStart = aStart;
NS_ABORT_IF_FALSE(aStart + length <= thisLength, "Er, what?");
// Prune the list of blobs if we can
PRUint32 i;
for (i = 0; length && skipStart && i < mBlobs.Length(); i++) {
nsIDOMBlob* blob = mBlobs[i].get();
PRUint64 l;
rv = blob->GetSize(&l);
NS_ENSURE_SUCCESS(rv, rv);
if (skipStart < l) {
PRInt64 upperBound = NS_MIN<PRInt64>(l - skipStart, length);
nsCOMPtr<nsIDOMBlob> firstBlob;
rv = mBlobs.ElementAt(i)->MozSlice(skipStart, skipStart + upperBound,
aContentType, 2,
getter_AddRefs(firstBlob));
NS_ENSURE_SUCCESS(rv, rv);
// Avoid wrapping a single blob inside an nsDOMMultipartBlob
if (length == upperBound) {
firstBlob.forget(aBlob);
return NS_OK;
}
blobs.AppendElement(firstBlob);
length -= upperBound;
i++;
break;
}
skipStart -= l;
}
// Now append enough blobs until we're done
for (; length && i < mBlobs.Length(); i++) {
nsIDOMBlob* blob = mBlobs[i].get();
PRUint64 l;
rv = blob->GetSize(&l);
NS_ENSURE_SUCCESS(rv, rv);
if (length < l) {
nsCOMPtr<nsIDOMBlob> lastBlob;
rv = mBlobs.ElementAt(i)->MozSlice(0, length, aContentType, 2,
getter_AddRefs(lastBlob));
NS_ENSURE_SUCCESS(rv, rv);
blobs.AppendElement(lastBlob);
} else {
blobs.AppendElement(blob);
}
length -= NS_MIN<PRInt64>(l, length);
}
// we can create our blob now
nsCOMPtr<nsIDOMBlob> blob = new nsDOMMultipartBlob(blobs, aContentType);
blob.forget(aBlob);
return NS_OK;
}
class nsDOMBlobBuilder : public nsIDOMBlobBuilder
{
public:
nsDOMBlobBuilder()
: mData(nsnull), mDataLen(0), mDataBufferLen(0)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMBLOBBUILDER
protected:
nsresult AppendVoidPtr(void* aData, PRUint32 aLength);
nsresult AppendString(JSString* aString, JSContext* aCx);
nsresult AppendBlob(nsIDOMBlob* aBlob);
nsresult AppendArrayBuffer(js::ArrayBuffer* aBuffer);
bool ExpandBufferSize(PRUint64 aSize)
{
if (mDataBufferLen >= mDataLen + aSize) {
mDataLen += aSize;
return true;
}
// Start at 1 or we'll loop forever.
CheckedUint32 bufferLen = NS_MAX<PRUint32>(mDataBufferLen, 1);
while (bufferLen.valid() && bufferLen.value() < mDataLen + aSize)
bufferLen *= 2;
if (!bufferLen.valid())
return false;
// PR_ memory functions are still fallible
void* data = PR_Realloc(mData, bufferLen.value());
if (!data)
return false;
mData = data;
mDataBufferLen = bufferLen.value();
mDataLen += aSize;
return true;
}
void Flush() {
if (mData) {
// If we have some data, create a blob for it
// and put it on the stack
nsCOMPtr<nsIDOMBlob> blob =
new nsDOMMemoryFile(mData, mDataLen, EmptyString(), EmptyString());
mBlobs.AppendElement(blob);
mData = nsnull; // The nsDOMMemoryFile takes ownership of the buffer
mDataLen = 0;
mDataBufferLen = 0;
}
}
nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
void* mData;
PRUint64 mDataLen;
PRUint64 mDataBufferLen;
};
DOMCI_DATA(MozBlobBuilder, nsDOMBlobBuilder)
NS_IMPL_ADDREF(nsDOMBlobBuilder)
NS_IMPL_RELEASE(nsDOMBlobBuilder)
NS_INTERFACE_MAP_BEGIN(nsDOMBlobBuilder)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlobBuilder)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozBlobBuilder)
NS_INTERFACE_MAP_END
nsresult
nsDOMBlobBuilder::AppendVoidPtr(void* aData, PRUint32 aLength)
{
NS_ENSURE_ARG_POINTER(aData);
PRUint64 offset = mDataLen;
if (!ExpandBufferSize(aLength))
return NS_ERROR_OUT_OF_MEMORY;
memcpy((char*)mData + offset, aData, aLength);
return NS_OK;
}
nsresult
nsDOMBlobBuilder::AppendString(JSString* aString, JSContext* aCx)
{
nsDependentJSString xpcomStr;
if (!xpcomStr.init(aCx, aString)) {
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
NS_ConvertUTF16toUTF8 utf8Str(xpcomStr);
return AppendVoidPtr((void*)utf8Str.Data(),
utf8Str.Length());
}
nsresult
nsDOMBlobBuilder::AppendBlob(nsIDOMBlob* aBlob)
{
NS_ENSURE_ARG_POINTER(aBlob);
Flush();
mBlobs.AppendElement(aBlob);
return NS_OK;
}
nsresult
nsDOMBlobBuilder::AppendArrayBuffer(js::ArrayBuffer* aBuffer)
{
return AppendVoidPtr(aBuffer->data, aBuffer->byteLength);
}
/* nsIDOMBlob getBlob ([optional] in DOMString contentType); */
NS_IMETHODIMP
nsDOMBlobBuilder::GetBlob(const nsAString& aContentType,
nsIDOMBlob** aBlob)
{
NS_ENSURE_ARG(aBlob);
Flush();
nsCOMPtr<nsIDOMBlob> blob = new nsDOMMultipartBlob(mBlobs,
aContentType);
blob.forget(aBlob);
// NB: This is a willful violation of the spec. The spec says that
// the existing contents of the BlobBuilder should be included
// in the next blob produced. This seems silly and has been raised
// on the WHATWG listserv.
mBlobs.Clear();
return NS_OK;
}
/* [implicit_jscontext] void append (in jsval data); */
NS_IMETHODIMP
nsDOMBlobBuilder::Append(const jsval& aData, JSContext* aCx)
{
// We need to figure out what our jsval is
// Is it an object?
if (JSVAL_IS_OBJECT(aData)) {
JSObject* obj = JSVAL_TO_OBJECT(aData);
NS_ASSERTION(obj, "Er, what?");
// Is it a Blob?
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
nsContentUtils::XPConnect()->
GetNativeOfWrapper(aCx, obj));
if (blob)
return AppendBlob(blob);
// Is it an array buffer?
if (js_IsArrayBuffer(obj)) {
js::ArrayBuffer* buffer = js::ArrayBuffer::fromJSObject(obj);
if (buffer)
return AppendArrayBuffer(buffer);
}
}
// If it's not a Blob or an ArrayBuffer, coerce it to a string
JSString* str = JS_ValueToString(aCx, aData);
NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
return AppendString(str, aCx);
}
nsresult NS_NewBlobBuilder(nsISupports* *aSupports)
{
nsDOMBlobBuilder* builder = new nsDOMBlobBuilder();
return CallQueryInterface(builder, aSupports);
}

Просмотреть файл

@ -49,6 +49,7 @@
#include "nsIConverterInputStream.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
#include "nsIInputStream.h"
#include "nsIIPCSerializable.h"
@ -139,6 +140,7 @@ DOMCI_DATA(Blob, nsDOMFile)
NS_INTERFACE_MAP_BEGIN(nsDOMFile)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFullFile)
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
@ -291,6 +293,13 @@ ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd)
}
}
NS_IMETHODIMP
nsDOMFile::Slice(PRUint64 aStart, PRUint64 aLength,
const nsAString& aContentType, nsIDOMBlob **aBlob)
{
return MozSlice(aStart, aStart + aLength, aContentType, 2, aBlob);
}
NS_IMETHODIMP
nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType, PRUint8 optional_argc,
@ -298,7 +307,7 @@ nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
{
*aBlob = nsnull;
// Truncate aStart and aEnd so that we stay within this file.
// Truncate aLength and aStart so that we stay within this file.
PRUint64 thisLength;
nsresult rv = GetSize(&thisLength);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -481,8 +481,6 @@ _TEST_FILES2 = \
bug638112-response.txt \
bug638112.sjs \
test_bug656283.html \
test_blobbuilder.html \
fileutils.js \
$(NULL)
# This test fails on the Mac for some reason

Просмотреть файл

@ -1,272 +0,0 @@
// Utility functions
var testRanCounter = 0;
var expectedTestCount = 0;
function testHasRun() {
//alert(testRanCounter);
++testRanCounter;
if (testRanCounter == expectedTestCount) {
SimpleTest.finish();
}
}
function testFile(file, contents, test) {
SimpleTest.requestLongerTimeout(2);
// Load file using FileReader
var r = new FileReader();
r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test);
r.readAsBinaryString(file);
expectedTestCount++;
// Load file using URL.createObjectURL and XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("GET", URL.createObjectURL(file));
xhr.onload = getXHRLoadHandler(contents, contents.length, false,
"XMLHttpRequest load of " + test);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send();
expectedTestCount++;
// Send file to server using FormData and XMLHttpRequest
xhr = new XMLHttpRequest();
xhr.onload = function(event) {
checkMPSubmission(JSON.parse(event.target.responseText),
[{ name: "hello", value: "world"},
{ name: "myfile",
value: contents,
fileName: file.name || "",
contentType: file.type || "application/octet-stream" }]);
testHasRun();
}
xhr.open("POST", "../../html/content/test/form_submit_server.sjs");
var fd = new FormData;
fd.append("hello", "world");
fd.append("myfile", file);
xhr.send(fd);
expectedTestCount++;
// Send file to server using plain XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("POST", "file_XHRSendData.sjs");
xhr.onload = function (event) {
is(event.target.getResponseHeader("Result-Content-Type"),
file.type ? file.type : null,
"request content-type in XMLHttpRequest send of " + test);
is(event.target.getResponseHeader("Result-Content-Length"),
file.size,
"request content-length in XMLHttpRequest send of " + test);
};
xhr.addEventListener("load",
getXHRLoadHandler(contents, contents.length, true,
"XMLHttpRequest send of " + test),
false);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send(file);
expectedTestCount++;
}
function getFileReaderLoadHandler(expectedResult, expectedLength, testName) {
return function (event) {
is(event.target.readyState, FileReader.DONE,
"[FileReader] readyState in test " + testName);
is(event.target.error, null,
"[FileReader] no error in test " + testName);
// Do not use |is(event.target.result, expectedResult, "...");| that may output raw binary data.
is(event.target.result.length, expectedResult.length,
"[FileReader] Length of result in test " + testName);
ok(event.target.result == expectedResult,
"[FileReader] Content of result in test " + testName);
is(event.lengthComputable, true,
"[FileReader] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[FileReader] Loaded length in test " + testName);
is(event.total, expectedLength,
"[FileReader] Total length in test " + testName);
testHasRun();
}
}
function getXHRLoadHandler(expectedResult, expectedLength, statusWorking, testName) {
return function (event) {
is(event.target.readyState, 4,
"[XHR] readyState in test " + testName);
if (statusWorking) {
is(event.target.status, 200,
"[XHR] no error in test " + testName);
}
else {
todo(event.target.status, 200,
"[XHR] no error in test " + testName);
}
// Do not use |is(convertXHRBinary(event.target.responseText), expectedResult, "...");| that may output raw binary data.
var convertedData = convertXHRBinary(event.target.responseText);
is(convertedData.length, expectedResult.length,
"[XHR] Length of result in test " + testName);
ok(convertedData == expectedResult,
"[XHR] Content of result in test " + testName);
is(event.lengthComputable, true,
"[XHR] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[XHR] Loaded length in test " + testName);
is(event.total, expectedLength,
"[XHR] Total length in test " + testName);
testHasRun();
}
}
function convertXHRBinary(s) {
var res = "";
for (var i = 0; i < s.length; ++i) {
res += String.fromCharCode(s.charCodeAt(i) & 255);
}
return res;
}
function testHasRun() {
//alert(testRanCounter);
++testRanCounter;
if (testRanCounter == expectedTestCount) {
SimpleTest.finish();
}
}
function createFileWithData(fileData) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append("fileAPItestfile2-" + fileNum);
fileNum++;
var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
return fileList.files[0];
}
function gc() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
function checkMPSubmission(sub, expected) {
function getPropCount(o) {
var x, l = 0;
for (x in o) ++l;
return l;
}
is(sub.length, expected.length,
"Correct number of items");
var i;
for (i = 0; i < expected.length; ++i) {
if (!("fileName" in expected[i])) {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"",
"Correct name (A)");
is (getPropCount(sub[i].headers), 1,
"Wrong number of headers (A)");
}
else {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"; filename=\"" +
expected[i].fileName + "\"",
"Correct name (B)");
is(sub[i].headers["Content-Type"],
expected[i].contentType,
"Correct content type (B)");
is (getPropCount(sub[i].headers), 2,
"Wrong number of headers (B)");
}
// Do not use |is(sub[i].body, expected[i].value, "...");| that may output raw binary data.
is(sub[i].body.length, expected[i].value.length,
"Length of correct value");
ok(sub[i].body == expected[i].value,
"Content of correct value");
}
}
function testSlice(file, size, type, contents, fileType) {
is(file.type, type, fileType + " file is correct type");
is(file.size, size, fileType + " file is correct size");
ok(file instanceof File, fileType + " file is a File");
ok(file instanceof Blob, fileType + " file is also a Blob");
var slice = file.mozSlice(0, size);
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
slice = file.mozSlice(0, 1234);
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
ok(!(slice instanceof File), fileType + " sized slice is not a File");
slice = file.mozSlice(0, size, "foo/bar");
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
slice = file.mozSlice(0, 5432, "foo/bar");
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
var indexes = [[0, size, size],
[0, 1234, 1234],
[size-500, size, 500],
[size-500, size+500, 500],
[size+500, size+1500, 0],
[0, 0, 0],
[1000, 1000, 0],
[size, size, 0],
[0, undefined, size],
[100, undefined, size-100],
[-100, undefined, 100],
[100, -100, size-200],
[-size-100, undefined, size],
[-2*size-100, 500, 500],
[0, -size-100, 0],
[100, -size-100, 0],
[50, -size+100, 50],
[0, 33000, 33000],
[1000, 34000, 33000],
];
for (var i = 0; i < indexes.length; ++i) {
var sliceContents;
var testName;
if (indexes[i][1] == undefined) {
slice = file.mozSlice(indexes[i][0]);
sliceContents = contents.slice(indexes[i][0]);
testName = fileType + " slice(" + indexes[i][0] + ")";
}
else {
slice = file.mozSlice(indexes[i][0], indexes[i][1]);
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
}
is(slice.type, "", testName + " type");
is(slice.size, indexes[i][2], testName + " size");
is(sliceContents.length, indexes[i][2], testName + " data size");
testFile(slice, sliceContents, testName);
}
// Slice of slice
var slice = file.mozSlice(0, 40000);
testFile(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
// ...of slice of slice
slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
SpecialPowers.gc();
testFile(slice, contents.slice(5400, 5700), "file slice slice slice");
}

Просмотреть файл

@ -1,135 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=648997
-->
<head>
<title>Test for Bug 648997</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="fileutils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=648997">Mozilla Bug 648997</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript;version=1.7">
// We're prefixing still
window.BlobBuilder = window.MozBlobBuilder;
/** Test for Bug 648997 **/
var blobBuilder = BlobBuilder();
ok(blobBuilder, "BlobBuilder should exist");
ok(blobBuilder.append, "BlobBuilder should have an append method");
ok(blobBuilder.getBlob, "BlobBuilder should have a getBlob method");
try {
blobBuilder.append();
ok(false, "NOT REACHED");
} catch(e) {
ok(true, "an empty argument to append should throw");
}
blobBuilder.append("squiggle");
let blob1 = blobBuilder.getBlob();
blobBuilder.append("ohai");
let blob2 = blobBuilder.getBlob();
let aB = new ArrayBuffer(16);
var int8View = new Int8Array(aB);
for (var i = 0; i < 16; i++) {
int8View[i] = i+65;
}
let testData =
[
// Test 3 strings
[["foo", "bar", "baz"], [{start: 0, length: 9, contents: "foobarbaz"},
{start: 0, length: 3, contents: "foo"},
{start: 3, length:6, contents: "barbaz"},
{start: 6, length: 3, contents: "baz"},
{start: 6, length: 6, elength: 3, contents: "baz"},
{start: 0, length: 9, contents: "foobarbaz"},
{start: 0, length: 11, elength: 9, contents: "foobarbaz"},
{start: 10, length: 5, elength: 0, contents: ""}]],
// Test string, Blob, string
[["foo", blob1, "baz"], [{start: 0, length: 3, contents: "foo"},
{start: 3, length: 8, contents: "squiggle"},
{start: 2, length: 2, contents: "os"},
{start: 10, length: 2, contents: "eb"}]],
// Test blob, string, blob
[[blob1, "foo", blob1], [{start: 0, length: 8, contents: "squiggle"},
{start: 7, length: 2, contents: "ef"},
{start: 10, length: 2, contents: "os"},
{start: 1, length: 3, contents: "qui"},
{start: 12, length: 3, contents: "qui"},
{start: 40, length: 20, elength: 0, contents: ""}]],
// Test blobs all the way down
[[blob2, blob1, blob2], [{start: 0, length: 4, contents: "ohai"},
{start: 4, length: 8, contents: "squiggle"},
{start: 12, length: 4, contents: "ohai"},
{start: 1, length: 2, contents: "ha"},
{start: 5, length: 4, contents: "quig"}]],
// Test an array buffer
[[aB, blob1, "foo"], [{start: 0, length: 8, contents: "ABCDEFGH"},
{start: 8, length:10, contents: "IJKLMNOPsq"},
{start: 17, length: 3, contents: "qui"},
{start: 4, length: 8, contents: "EFGHIJKL"}]],
// Test type coercion of a number
[[3, aB, "foo"], [{start: 0, length: 8, contents: "3ABCDEFG"},
{start: 8, length:10, contents: "HIJKLMNOPf"},
{start: 17, length: 4, elength: 3, contents: "foo"},
{start: 4, length: 8, contents: "DEFGHIJK"}]]
];
let testCounter = 0;
function doTest(data) {
testCounter++;
[blobs, tests] = data;
function runTest(test) {
let bb = new BlobBuilder();
ok(bb, "BlobBuilder should exist");
function doAppend(blob) {
bb.append(blob);
blob.expando = bb; // Do we leak?
}
blobs.forEach(doAppend);
ok(true, "Test " + testCounter + " appended all successfully");
let blob = bb.getBlob();
ok(blob, "Test " + testCounter + " got blob");
ok(blob instanceof Blob, "Test " + testCounter + " blob is a Blob");
//ok(!(blob instanceof File), "Test " + testCounter + " blob is not a File");
let slice = blob.mozSlice(test.start, test.start + test.length);
ok(slice, "Test " + testCounter + " got slice");
ok(slice instanceof Blob, "Test " + testCounter + " slice is a Blob");
//ok(!(slice instanceof File), "Test " + testCounter + " slice is not a File");
is(slice.size,"elength" in test ? test.elength : test.length,
"Test " + testCounter + " slice is correct size");
testFile(slice, test.contents, "Test " + testCounter,
"elength" in test ? test.elength : test.length);
}
tests.forEach(runTest);
SpecialPowers.gc();
}
SimpleTest.waitForExplicitFinish();
testData.forEach(doTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -7,7 +7,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=575946
<title>Test for Bug 575946</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="fileutils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
@ -24,6 +23,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=575946
<pre id="test">
<script class="testbody" type="text/javascript">
var fileNum = 1;
var testRanCounter = 0;
var expectedTestCount = 0;
SimpleTest.waitForExplicitFinish();
// Create files containing data we'll test with. We'll want long
@ -68,8 +69,83 @@ ok(size > 65536, "test data sufficiently large");
// Test that basic properties work
testSlice(memFile, size, "image/png", fileData, "memFile");
testSlice(fileFile, size, "", fileData, "fileFile");
function testFile(file, size, type, contents, fileType) {
is(file.type, type, fileType + " file is correct type");
is(file.size, size, fileType + " file is correct size");
ok(file instanceof File, fileType + " file is a File");
ok(file instanceof Blob, fileType + " file is also a Blob");
var slice = file.mozSlice(0, size);
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
slice = file.mozSlice(0, 1234);
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
ok(!(slice instanceof File), fileType + " sized slice is not a File");
slice = file.mozSlice(0, size, "foo/bar");
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
slice = file.mozSlice(0, 5432, "foo/bar");
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
var indexes = [[0, size, size],
[0, 1234, 1234],
[size-500, size, 500],
[size-500, size+500, 500],
[size+500, size+1500, 0],
[0, 0, 0],
[1000, 1000, 0],
[size, size, 0],
[0, undefined, size],
[100, undefined, size-100],
[-100, undefined, 100],
[100, -100, size-200],
[-size-100, undefined, size],
[-2*size-100, 500, 500],
[0, -size-100, 0],
[100, -size-100, 0],
[50, -size+100, 50],
[0, 33000, 33000],
[1000, 34000, 33000],
];
for (var i = 0; i < indexes.length; ++i) {
var sliceContents;
var testName;
if (indexes[i][1] == undefined) {
slice = file.mozSlice(indexes[i][0]);
sliceContents = contents.slice(indexes[i][0]);
testName = fileType + " slice(" + indexes[i][0] + ")";
}
else {
slice = file.mozSlice(indexes[i][0], indexes[i][1]);
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
}
is(slice.type, "", testName + " type");
is(slice.size, indexes[i][2], testName + " size");
is(sliceContents.length, indexes[i][2], testName + " data size");
checkFileContents(slice, sliceContents, testName);
}
// Slice of slice
var slice = file.mozSlice(0, 40000);
checkFileContents(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
// ...of slice of slice
slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
gc();
checkFileContents(slice, contents.slice(5400, 5700), "file slice slice slice");
}
testFile(memFile, size, "image/png", fileData, "memFile");
testFile(fileFile, size, "", fileData, "fileFile");
// Try loading directly from slice into an image
@ -133,6 +209,192 @@ img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinary
img.onload = imageLoadHandler;
expectedTestCount++;
// Utility functions
function checkFileContents(file, contents, test) {
SimpleTest.requestLongerTimeout(2);
// Load file using FileReader
var r = new FileReader();
r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test);
r.readAsBinaryString(file);
expectedTestCount++;
// Load file using URL.createObjectURL and XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("GET", URL.createObjectURL(file));
xhr.onload = getXHRLoadHandler(contents, contents.length, false,
"XMLHttpRequest load of " + test);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send();
expectedTestCount++;
// Send file to server using FormData and XMLHttpRequest
xhr = new XMLHttpRequest();
xhr.onload = function(event) {
checkMPSubmission(JSON.parse(event.target.responseText),
[{ name: "hello", value: "world"},
{ name: "myfile",
value: contents,
fileName: file.name || "",
contentType: file.type || "application/octet-stream" }]);
testHasRun();
}
xhr.open("POST", "../../html/content/test/form_submit_server.sjs");
var fd = new FormData;
fd.append("hello", "world");
fd.append("myfile", file);
xhr.send(fd);
expectedTestCount++;
// Send file to server using plain XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("POST", "file_XHRSendData.sjs");
xhr.onload = function (event) {
is(event.target.getResponseHeader("Result-Content-Type"),
file.type ? file.type : null,
"request content-type in XMLHttpRequest send of " + test);
is(event.target.getResponseHeader("Result-Content-Length"),
file.size,
"request content-length in XMLHttpRequest send of " + test);
};
xhr.addEventListener("load",
getXHRLoadHandler(contents, contents.length, true,
"XMLHttpRequest send of " + test),
false);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send(file);
expectedTestCount++;
}
function getFileReaderLoadHandler(expectedResult, expectedLength, testName) {
return function (event) {
is(event.target.readyState, FileReader.DONE,
"[FileReader] readyState in test " + testName);
is(event.target.error, null,
"[FileReader] no error in test " + testName);
// Do not use |is(event.target.result, expectedResult, "...");| that may output raw binary data.
is(event.target.result.length, expectedResult.length,
"[FileReader] Length of result in test " + testName);
ok(event.target.result == expectedResult,
"[FileReader] Content of result in test " + testName);
is(event.lengthComputable, true,
"[FileReader] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[FileReader] Loaded length in test " + testName);
is(event.total, expectedLength,
"[FileReader] Total length in test " + testName);
testHasRun();
}
}
function getXHRLoadHandler(expectedResult, expectedLength, statusWorking, testName) {
return function (event) {
is(event.target.readyState, 4,
"[XHR] readyState in test " + testName);
if (statusWorking) {
is(event.target.status, 200,
"[XHR] no error in test " + testName);
}
else {
todo(event.target.status, 200,
"[XHR] no error in test " + testName);
}
// Do not use |is(convertXHRBinary(event.target.responseText), expectedResult, "...");| that may output raw binary data.
var convertedData = convertXHRBinary(event.target.responseText);
is(convertedData.length, expectedResult.length,
"[XHR] Length of result in test " + testName);
ok(convertedData == expectedResult,
"[XHR] Content of result in test " + testName);
is(event.lengthComputable, true,
"[XHR] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[XHR] Loaded length in test " + testName);
is(event.total, expectedLength,
"[XHR] Total length in test " + testName);
testHasRun();
}
}
function convertXHRBinary(s) {
var res = "";
for (var i = 0; i < s.length; ++i) {
res += String.fromCharCode(s.charCodeAt(i) & 255);
}
return res;
}
function testHasRun() {
//alert(testRanCounter);
++testRanCounter;
if (testRanCounter == expectedTestCount) {
SimpleTest.finish();
}
}
function createFileWithData(fileData) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append("fileAPItestfile2-" + fileNum);
fileNum++;
var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
return fileList.files[0];
}
function gc() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
function checkMPSubmission(sub, expected) {
function getPropCount(o) {
var x, l = 0;
for (x in o) ++l;
return l;
}
is(sub.length, expected.length,
"Correct number of items");
var i;
for (i = 0; i < expected.length; ++i) {
if (!("fileName" in expected[i])) {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"",
"Correct name (A)");
is (getPropCount(sub[i].headers), 1,
"Wrong number of headers (A)");
}
else {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"; filename=\"" +
expected[i].fileName + "\"",
"Correct name (B)");
is(sub[i].headers["Content-Type"],
expected[i].contentType,
"Correct content type (B)");
is (getPropCount(sub[i].headers), 2,
"Wrong number of headers (B)");
}
// Do not use |is(sub[i].body, expected[i].value, "...");| that may output raw binary data.
is(sub[i].body.length, expected[i].value.length,
"Length of correct value");
ok(sub[i].body == expected[i].value,
"Content of correct value");
}
}
</script>
</pre>
</body> </html>

Просмотреть файл

@ -1331,8 +1331,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(XULCommandEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozBlobBuilder, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(CommandEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1577,7 +1575,6 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] =
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFile::NewFile)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
};
nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
@ -4004,10 +4001,12 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
DOM_CLASSINFO_MAP_END
@ -4032,10 +4031,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMStringMap)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozBlobBuilder, nsIDOMBlobBuilder)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlobBuilder)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)

Просмотреть файл

@ -406,7 +406,6 @@ DOMCI_CLASS(FileException)
DOMCI_CLASS(FileError)
DOMCI_CLASS(FileReader)
DOMCI_CLASS(MozURLProperty)
DOMCI_CLASS(MozBlobBuilder)
DOMCI_CLASS(DOMStringMap)