зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 4 changesets (bug 1619518
) for mochitest failures at test_temporaryFileBlob.html. CLOSED TREE
Backed out changeset f848fd145194 (bug1619518
) Backed out changeset eb4b8aa164e8 (bug1619518
) Backed out changeset 403e9b8e2040 (bug1619518
) Backed out changeset aa25ea873fa9 (bug1619518
)
This commit is contained in:
Родитель
905f2e1beb
Коммит
e05aaf88c7
|
@ -252,7 +252,7 @@ class MOZ_STACK_CLASS FormDataParser {
|
|||
}
|
||||
p = nullptr;
|
||||
|
||||
RefPtr<Blob> file = File::CreateMemoryFileWithCustomLastModified(
|
||||
RefPtr<Blob> file = File::CreateMemoryFile(
|
||||
mParentObject, reinterpret_cast<void*>(copy), body.Length(),
|
||||
NS_ConvertUTF8toUTF16(mFilename), NS_ConvertUTF8toUTF16(mContentType),
|
||||
/* aLastModifiedDate */ 0);
|
||||
|
|
|
@ -397,8 +397,8 @@ already_AddRefed<File> DataTransferItem::CreateFileFromInputStream(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return File::CreateMemoryFileWithLastModifiedNow(global, data, available,
|
||||
fileName, mType);
|
||||
return File::CreateMemoryFile(global, data, available, fileName, mType,
|
||||
PR_Now());
|
||||
}
|
||||
|
||||
void DataTransferItem::GetAsString(FunctionStringCallback* aCallback,
|
||||
|
|
|
@ -48,11 +48,56 @@ void BaseBlobImpl::GetType(nsAString& aType) { aType = mContentType; }
|
|||
|
||||
int64_t BaseBlobImpl::GetLastModified(ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
if (IsDateUnknown()) {
|
||||
mLastModificationDate =
|
||||
nsRFPService::ReduceTimePrecisionAsUSecs(PR_Now(), 0);
|
||||
// mLastModificationDate is an absolute timestamp so we supply a zero
|
||||
// context mix-in
|
||||
}
|
||||
|
||||
return mLastModificationDate / PR_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
void BaseBlobImpl::SetLastModified(int64_t aLastModified) {
|
||||
mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
int64_t BaseBlobImpl::GetFileId() { return -1; }
|
||||
|
||||
nsresult BaseBlobImpl::GetSendInfo(nsIInputStream** aBody,
|
||||
uint64_t* aContentLength,
|
||||
nsACString& aContentType,
|
||||
nsACString& aCharset) {
|
||||
MOZ_ASSERT(aContentLength);
|
||||
|
||||
ErrorResult rv;
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
CreateInputStream(getter_AddRefs(stream), rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
*aContentLength = GetSize(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
nsAutoString contentType;
|
||||
GetType(contentType);
|
||||
|
||||
if (contentType.IsEmpty()) {
|
||||
aContentType.SetIsVoid(true);
|
||||
} else {
|
||||
CopyUTF16toUTF8(contentType, aContentType);
|
||||
}
|
||||
|
||||
aCharset.Truncate();
|
||||
|
||||
stream.forget(aBody);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
uint64_t BaseBlobImpl::NextSerialNumber() {
|
||||
static Atomic<uint64_t> nextSerialNumber;
|
||||
|
|
|
@ -12,13 +12,8 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FileBlobImpl;
|
||||
|
||||
class BaseBlobImpl : public BlobImpl {
|
||||
friend class FileBlobImpl;
|
||||
|
||||
public:
|
||||
// File constructor.
|
||||
BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aName,
|
||||
const nsAString& aContentType, uint64_t aLength,
|
||||
int64_t aLastModifiedDate)
|
||||
|
@ -34,7 +29,20 @@ class BaseBlobImpl : public BlobImpl {
|
|||
mContentType.SetIsVoid(false);
|
||||
}
|
||||
|
||||
// Blob constructor without starting point.
|
||||
BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aName,
|
||||
const nsAString& aContentType, uint64_t aLength)
|
||||
: mBlobImplType(aBlobImplType),
|
||||
mIsFile(true),
|
||||
mContentType(aContentType),
|
||||
mName(aName),
|
||||
mStart(0),
|
||||
mLength(aLength),
|
||||
mLastModificationDate(INT64_MAX),
|
||||
mSerialNumber(NextSerialNumber()) {
|
||||
// Ensure non-null mContentType by default
|
||||
mContentType.SetIsVoid(false);
|
||||
}
|
||||
|
||||
BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aContentType,
|
||||
uint64_t aLength)
|
||||
: mBlobImplType(aBlobImplType),
|
||||
|
@ -42,13 +50,12 @@ class BaseBlobImpl : public BlobImpl {
|
|||
mContentType(aContentType),
|
||||
mStart(0),
|
||||
mLength(aLength),
|
||||
mLastModificationDate(0),
|
||||
mLastModificationDate(INT64_MAX),
|
||||
mSerialNumber(NextSerialNumber()) {
|
||||
// Ensure non-null mContentType by default
|
||||
mContentType.SetIsVoid(false);
|
||||
}
|
||||
|
||||
// Blob constructor with starting point.
|
||||
BaseBlobImpl(const nsAString& aBlobImplType, const nsAString& aContentType,
|
||||
uint64_t aStart, uint64_t aLength)
|
||||
: mBlobImplType(aBlobImplType),
|
||||
|
@ -56,8 +63,9 @@ class BaseBlobImpl : public BlobImpl {
|
|||
mContentType(aContentType),
|
||||
mStart(aStart),
|
||||
mLength(aLength),
|
||||
mLastModificationDate(0),
|
||||
mLastModificationDate(INT64_MAX),
|
||||
mSerialNumber(NextSerialNumber()) {
|
||||
MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
|
||||
// Ensure non-null mContentType by default
|
||||
mContentType.SetIsVoid(false);
|
||||
}
|
||||
|
@ -70,6 +78,8 @@ class BaseBlobImpl : public BlobImpl {
|
|||
|
||||
virtual int64_t GetLastModified(ErrorResult& aRv) override;
|
||||
|
||||
virtual void SetLastModified(int64_t aLastModified) override;
|
||||
|
||||
virtual void GetMozFullPath(nsAString& aName,
|
||||
SystemCallerGuarantee /* unused */,
|
||||
ErrorResult& aRv) override;
|
||||
|
@ -108,6 +118,10 @@ class BaseBlobImpl : public BlobImpl {
|
|||
|
||||
virtual int64_t GetFileId() override;
|
||||
|
||||
virtual nsresult GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
||||
nsACString& aContentType,
|
||||
nsACString& aCharset) override;
|
||||
|
||||
virtual void SetLazyData(const nsAString& aName,
|
||||
const nsAString& aContentType, uint64_t aLength,
|
||||
int64_t aLastModifiedDate) override {
|
||||
|
@ -120,8 +134,14 @@ class BaseBlobImpl : public BlobImpl {
|
|||
|
||||
virtual bool IsMemoryFile() const override { return false; }
|
||||
|
||||
virtual bool IsDateUnknown() const override {
|
||||
return mIsFile && mLastModificationDate == INT64_MAX;
|
||||
}
|
||||
|
||||
virtual bool IsFile() const override { return mIsFile; }
|
||||
|
||||
virtual bool IsSizeUnknown() const override { return mLength == UINT64_MAX; }
|
||||
|
||||
virtual void GetBlobImplType(nsAString& aBlobImplType) const override {
|
||||
aBlobImplType = mBlobImplType;
|
||||
}
|
||||
|
|
|
@ -61,38 +61,6 @@ already_AddRefed<BlobImpl> BlobImpl::Slice(const Optional<int64_t>& aStart,
|
|||
return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
|
||||
}
|
||||
|
||||
nsresult BlobImpl::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
||||
nsACString& aContentType, nsACString& aCharset) {
|
||||
MOZ_ASSERT(aContentLength);
|
||||
|
||||
ErrorResult rv;
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
CreateInputStream(getter_AddRefs(stream), rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
*aContentLength = GetSize(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
nsAutoString contentType;
|
||||
GetType(contentType);
|
||||
|
||||
if (contentType.IsEmpty()) {
|
||||
aContentType.SetIsVoid(true);
|
||||
} else {
|
||||
CopyUTF16toUTF8(contentType, aContentType);
|
||||
}
|
||||
|
||||
aCharset.Truncate();
|
||||
|
||||
stream.forget(aBody);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -41,6 +41,8 @@ class BlobImpl : public nsISupports {
|
|||
|
||||
virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
|
||||
|
||||
virtual void SetLastModified(int64_t aLastModified) = 0;
|
||||
|
||||
virtual void GetMozFullPath(nsAString& aName,
|
||||
SystemCallerGuarantee /* unused */,
|
||||
ErrorResult& aRv) = 0;
|
||||
|
@ -83,8 +85,9 @@ class BlobImpl : public nsISupports {
|
|||
|
||||
virtual int64_t GetFileId() = 0;
|
||||
|
||||
nsresult GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
||||
nsACString& aContentType, nsACString& aCharset);
|
||||
virtual nsresult GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
||||
nsACString& aContentType,
|
||||
nsACString& aCharset) = 0;
|
||||
|
||||
virtual void SetLazyData(const nsAString& aName,
|
||||
const nsAString& aContentType, uint64_t aLength,
|
||||
|
@ -92,6 +95,10 @@ class BlobImpl : public nsISupports {
|
|||
|
||||
virtual bool IsMemoryFile() const = 0;
|
||||
|
||||
virtual bool IsSizeUnknown() const = 0;
|
||||
|
||||
virtual bool IsDateUnknown() const = 0;
|
||||
|
||||
virtual bool IsFile() const = 0;
|
||||
|
||||
// Returns true if the BlobImpl is backed by an nsIFile and the underlying
|
||||
|
|
|
@ -16,11 +16,15 @@ class EmptyBlobImpl final : public BaseBlobImpl {
|
|||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(EmptyBlobImpl, BaseBlobImpl)
|
||||
|
||||
// Blob constructor.
|
||||
explicit EmptyBlobImpl(const nsAString& aContentType)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aContentType,
|
||||
0 /* aLength */) {}
|
||||
|
||||
EmptyBlobImpl(const nsAString& aName, const nsAString& aContentType,
|
||||
int64_t aLastModifiedDate)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aName, aContentType, 0,
|
||||
aLastModifiedDate) {}
|
||||
|
||||
virtual void CreateInputStream(nsIInputStream** aStream,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
|
|
|
@ -38,28 +38,37 @@ File* File::Create(nsIGlobalObject* aGlobal, BlobImpl* aImpl) {
|
|||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<File> File::CreateMemoryFileWithCustomLastModified(
|
||||
nsIGlobalObject* aGlobal, void* aMemoryBuffer, uint64_t aLength,
|
||||
const nsAString& aName, const nsAString& aContentType,
|
||||
int64_t aLastModifiedDate) {
|
||||
RefPtr<MemoryBlobImpl> blobImpl =
|
||||
MemoryBlobImpl::CreateWithCustomLastModified(
|
||||
aMemoryBuffer, aLength, aName, aContentType, aLastModifiedDate);
|
||||
MOZ_ASSERT(blobImpl);
|
||||
already_AddRefed<File> File::Create(nsIGlobalObject* aGlobal,
|
||||
const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength,
|
||||
int64_t aLastModifiedDate) {
|
||||
MOZ_ASSERT(aGlobal);
|
||||
if (NS_WARN_IF(!aGlobal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<File> file = File::Create(aGlobal, blobImpl);
|
||||
RefPtr<File> file = new File(
|
||||
aGlobal, new BaseBlobImpl(NS_LITERAL_STRING("BaseBlobImpl"), aName,
|
||||
aContentType, aLength, aLastModifiedDate));
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<File> File::CreateMemoryFileWithLastModifiedNow(
|
||||
nsIGlobalObject* aGlobal, void* aMemoryBuffer, uint64_t aLength,
|
||||
const nsAString& aName, const nsAString& aContentType) {
|
||||
RefPtr<MemoryBlobImpl> blobImpl = MemoryBlobImpl::CreateWithLastModifiedNow(
|
||||
aMemoryBuffer, aLength, aName, aContentType);
|
||||
MOZ_ASSERT(blobImpl);
|
||||
already_AddRefed<File> File::CreateMemoryFile(nsIGlobalObject* aGlobal,
|
||||
void* aMemoryBuffer,
|
||||
uint64_t aLength,
|
||||
const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
int64_t aLastModifiedDate) {
|
||||
MOZ_ASSERT(aGlobal);
|
||||
if (NS_WARN_IF(!aGlobal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<File> file = File::Create(aGlobal, blobImpl);
|
||||
RefPtr<File> file =
|
||||
new File(aGlobal, new MemoryBlobImpl(aMemoryBuffer, aLength, aName,
|
||||
aContentType, aLastModifiedDate));
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,19 +26,21 @@ class File final : public Blob {
|
|||
// Check impl->IsFile().
|
||||
static File* Create(nsIGlobalObject* aGlobal, BlobImpl* aImpl);
|
||||
|
||||
static already_AddRefed<File> Create(nsIGlobalObject* aGlobal,
|
||||
const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
uint64_t aLength,
|
||||
int64_t aLastModifiedDate);
|
||||
|
||||
// The returned File takes ownership of aMemoryBuffer. aMemoryBuffer will be
|
||||
// freed by free so it must be allocated by malloc or something
|
||||
// compatible with it.
|
||||
static already_AddRefed<File> CreateMemoryFileWithLastModifiedNow(
|
||||
nsIGlobalObject* aGlobal, void* aMemoryBuffer, uint64_t aLength,
|
||||
const nsAString& aName, const nsAString& aContentType);
|
||||
|
||||
// You should not use this method! Please consider to use the
|
||||
// CreateMemoryFileWithLastModifiedNow.
|
||||
static already_AddRefed<File> CreateMemoryFileWithCustomLastModified(
|
||||
nsIGlobalObject* aGlobal, void* aMemoryBuffer, uint64_t aLength,
|
||||
const nsAString& aName, const nsAString& aContentType,
|
||||
int64_t aLastModifiedDate);
|
||||
static already_AddRefed<File> CreateMemoryFile(nsIGlobalObject* aGlobal,
|
||||
void* aMemoryBuffer,
|
||||
uint64_t aLength,
|
||||
const nsAString& aName,
|
||||
const nsAString& aContentType,
|
||||
int64_t aLastModifiedDate);
|
||||
|
||||
// This method creates a BlobFileImpl for the new File object. This is
|
||||
// thread-safe, cross-process, cross-thread as any other BlobImpl, but, when
|
||||
|
|
|
@ -19,12 +19,11 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
FileBlobImpl::FileBlobImpl(nsIFile* aFile)
|
||||
: mMutex("FileBlobImpl::mMutex"),
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), EmptyString(),
|
||||
EmptyString(), UINT64_MAX, INT64_MAX),
|
||||
mMutex("FileBlobImpl::mMutex"),
|
||||
mFile(aFile),
|
||||
mSerialNumber(BaseBlobImpl::NextSerialNumber()),
|
||||
mStart(0),
|
||||
mFileId(-1),
|
||||
mIsFile(true),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
@ -37,15 +36,11 @@ FileBlobImpl::FileBlobImpl(nsIFile* aFile)
|
|||
FileBlobImpl::FileBlobImpl(const nsAString& aName,
|
||||
const nsAString& aContentType, uint64_t aLength,
|
||||
nsIFile* aFile)
|
||||
: mMutex("FileBlobImpl::mMutex"),
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
|
||||
aLength, UINT64_MAX),
|
||||
mMutex("FileBlobImpl::mMutex"),
|
||||
mFile(aFile),
|
||||
mContentType(aContentType),
|
||||
mName(aName),
|
||||
mSerialNumber(BaseBlobImpl::NextSerialNumber()),
|
||||
mStart(0),
|
||||
mFileId(-1),
|
||||
mLength(Some(aLength)),
|
||||
mIsFile(true),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
@ -55,16 +50,11 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName,
|
|||
FileBlobImpl::FileBlobImpl(const nsAString& aName,
|
||||
const nsAString& aContentType, uint64_t aLength,
|
||||
nsIFile* aFile, int64_t aLastModificationDate)
|
||||
: mMutex("FileBlobImpl::mMutex"),
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
|
||||
aLength, aLastModificationDate),
|
||||
mMutex("FileBlobImpl::mMutex"),
|
||||
mFile(aFile),
|
||||
mContentType(aContentType),
|
||||
mName(aName),
|
||||
mSerialNumber(BaseBlobImpl::NextSerialNumber()),
|
||||
mStart(0),
|
||||
mFileId(-1),
|
||||
mLength(Some(aLength)),
|
||||
mLastModified(Some(aLastModificationDate)),
|
||||
mIsFile(true),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
@ -72,15 +62,12 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName,
|
|||
}
|
||||
|
||||
FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
|
||||
const nsAString& aContentType)
|
||||
: mMutex("FileBlobImpl::mMutex"),
|
||||
const nsAString& aContentType,
|
||||
const nsAString& aBlobImplType)
|
||||
: BaseBlobImpl(aBlobImplType, aName, aContentType, UINT64_MAX, INT64_MAX),
|
||||
mMutex("FileBlobImpl::mMutex"),
|
||||
mFile(aFile),
|
||||
mContentType(aContentType),
|
||||
mName(aName),
|
||||
mSerialNumber(BaseBlobImpl::NextSerialNumber()),
|
||||
mStart(0),
|
||||
mFileId(-1),
|
||||
mIsFile(true),
|
||||
mWholeFile(true) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
@ -94,14 +81,11 @@ FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
|
|||
|
||||
FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
|
||||
uint64_t aLength, const nsAString& aContentType)
|
||||
: mMutex("FileBlobImpl::mMutex"),
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aContentType,
|
||||
aOther->mStart + aStart, aLength),
|
||||
mMutex("FileBlobImpl::mMutex"),
|
||||
mFile(aOther->mFile),
|
||||
mContentType(aContentType),
|
||||
mSerialNumber(BaseBlobImpl::NextSerialNumber()),
|
||||
mStart(aOther->mStart + aStart),
|
||||
mFileId(-1),
|
||||
mLength(Some(aLength)),
|
||||
mIsFile(false),
|
||||
mWholeFile(false) {
|
||||
MOZ_ASSERT(mFile, "must have file");
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
@ -138,7 +122,7 @@ void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
|
|||
uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mLength.isNothing()) {
|
||||
if (BaseBlobImpl::IsSizeUnknown()) {
|
||||
MOZ_ASSERT(mWholeFile,
|
||||
"Should only use lazy size when using the whole file");
|
||||
int64_t fileSize;
|
||||
|
@ -152,10 +136,10 @@ uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
mLength.emplace(fileSize);
|
||||
mLength = fileSize;
|
||||
}
|
||||
|
||||
return mLength.value();
|
||||
return mLength;
|
||||
}
|
||||
|
||||
class FileBlobImpl::GetTypeRunnable final : public WorkerMainThreadRunnable {
|
||||
|
@ -237,26 +221,22 @@ void FileBlobImpl::GetTypeInternal(nsAString& aType,
|
|||
aType = mContentType;
|
||||
}
|
||||
|
||||
void FileBlobImpl::GetBlobImplType(nsAString& aBlobImplType) const {
|
||||
aBlobImplType = NS_LITERAL_STRING("FileBlobImpl");
|
||||
}
|
||||
|
||||
int64_t FileBlobImpl::GetLastModified(ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mLastModified.isNothing()) {
|
||||
if (BaseBlobImpl::IsDateUnknown()) {
|
||||
PRTime msecs;
|
||||
aRv = mFile->GetLastModifiedTime(&msecs);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mLastModified.emplace(int64_t(msecs));
|
||||
mLastModificationDate = msecs;
|
||||
}
|
||||
|
||||
return mLastModified.value();
|
||||
return mLastModificationDate;
|
||||
}
|
||||
|
||||
const uint32_t sFileStreamFlags =
|
||||
|
@ -277,10 +257,8 @@ void FileBlobImpl::CreateInputStream(nsIInputStream** aStream,
|
|||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mLength.isSome());
|
||||
|
||||
RefPtr<SlicedInputStream> slicedInputStream =
|
||||
new SlicedInputStream(stream.forget(), mStart, mLength.value());
|
||||
new SlicedInputStream(stream.forget(), mStart, mLength);
|
||||
slicedInputStream.forget(aStream);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
#ifndef mozilla_dom_FileBlobImpl_h
|
||||
#define mozilla_dom_FileBlobImpl_h
|
||||
|
||||
#include "mozilla/dom/BlobImpl.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/dom/BaseBlobImpl.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
class nsIFile;
|
||||
|
@ -16,9 +15,9 @@ class nsIFile;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FileBlobImpl : public BlobImpl {
|
||||
class FileBlobImpl : public BaseBlobImpl {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(FileBlobImpl, BlobImpl)
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(FileBlobImpl, BaseBlobImpl)
|
||||
|
||||
// Create as a file
|
||||
explicit FileBlobImpl(nsIFile* aFile);
|
||||
|
@ -31,123 +30,64 @@ class FileBlobImpl : public BlobImpl {
|
|||
uint64_t aLength, nsIFile* aFile, int64_t aLastModificationDate);
|
||||
|
||||
// Create as a file with custom name
|
||||
FileBlobImpl(nsIFile* aFile, const nsAString& aName,
|
||||
const nsAString& aContentType);
|
||||
|
||||
void GetName(nsAString& aName) const override {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
aName = mName;
|
||||
}
|
||||
|
||||
void SetName(const nsAString& aName) { mName = aName; }
|
||||
|
||||
void GetDOMPath(nsAString& aPath) const override {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
aPath = mPath;
|
||||
}
|
||||
|
||||
void SetDOMPath(const nsAString& aPath) override {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
mPath = aPath;
|
||||
}
|
||||
|
||||
int64_t GetLastModified(ErrorResult& aRv) override;
|
||||
|
||||
void GetMozFullPath(nsAString& aFileName, SystemCallerGuarantee /* unused */,
|
||||
ErrorResult& aRv) override {
|
||||
MOZ_ASSERT(mIsFile, "Should only be called on files");
|
||||
|
||||
GetMozFullPathInternal(aFileName, aRv);
|
||||
}
|
||||
|
||||
void GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) override;
|
||||
|
||||
uint64_t GetSize(ErrorResult& aRv) override;
|
||||
|
||||
void GetType(nsAString& aType) override;
|
||||
|
||||
virtual void GetBlobImplType(nsAString& aBlobImplType) const override;
|
||||
|
||||
size_t GetAllocationSize() const override { return 0; }
|
||||
|
||||
size_t GetAllocationSize(
|
||||
FallibleTArray<BlobImpl*>& aVisitedBlobImpls) const override {
|
||||
return GetAllocationSize();
|
||||
}
|
||||
|
||||
uint64_t GetSerialNumber() const override { return mSerialNumber; }
|
||||
|
||||
const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const override {
|
||||
return nullptr;
|
||||
}
|
||||
FileBlobImpl(
|
||||
nsIFile* aFile, const nsAString& aName, const nsAString& aContentType,
|
||||
const nsAString& aBlobImplType = NS_LITERAL_STRING("FileBlobImpl"));
|
||||
|
||||
// Overrides
|
||||
virtual uint64_t GetSize(ErrorResult& aRv) override;
|
||||
virtual void GetType(nsAString& aType) override;
|
||||
virtual int64_t GetLastModified(ErrorResult& aRv) override;
|
||||
virtual void GetMozFullPathInternal(nsAString& aFullPath,
|
||||
ErrorResult& aRv) override;
|
||||
virtual void CreateInputStream(nsIInputStream** aInputStream,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
int64_t GetFileId() override { return mFileId; }
|
||||
virtual bool IsDirectory() const override;
|
||||
|
||||
void SetLazyData(const nsAString& aName, const nsAString& aContentType,
|
||||
uint64_t aLength, int64_t aLastModifiedDate) override {
|
||||
mName = aName;
|
||||
mContentType = aContentType;
|
||||
mIsFile = !aName.IsVoid();
|
||||
mLength.emplace(aLength);
|
||||
mLastModified.emplace(aLastModifiedDate);
|
||||
}
|
||||
// We always have size and date for this kind of blob.
|
||||
virtual bool IsSizeUnknown() const override { return false; }
|
||||
virtual bool IsDateUnknown() const override { return false; }
|
||||
|
||||
bool IsMemoryFile() const override { return false; }
|
||||
|
||||
bool IsFile() const override { return mIsFile; }
|
||||
|
||||
bool IsDirectory() const override;
|
||||
void SetName(const nsAString& aName) { mName = aName; }
|
||||
|
||||
void SetType(const nsAString& aType) { mContentType = aType; }
|
||||
|
||||
int64_t GetFileId() override { return mFileId; }
|
||||
|
||||
void SetFileId(int64_t aFileId) { mFileId = aFileId; }
|
||||
|
||||
void SetEmptySize() { mLength.emplace(0); }
|
||||
void SetEmptySize() { mLength = 0; }
|
||||
|
||||
void SetMozFullPath(const nsAString& aPath) { mMozFullPath = aPath; }
|
||||
|
||||
void SetLastModified(int64_t aLastModified) {
|
||||
mLastModified.emplace(aLastModified);
|
||||
}
|
||||
|
||||
protected:
|
||||
~FileBlobImpl() = default;
|
||||
virtual ~FileBlobImpl() = default;
|
||||
|
||||
// Create slice
|
||||
FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType);
|
||||
|
||||
already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType,
|
||||
ErrorResult& aRv) override;
|
||||
virtual already_AddRefed<BlobImpl> CreateSlice(uint64_t aStart,
|
||||
uint64_t aLength,
|
||||
const nsAString& aContentType,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
class GetTypeRunnable;
|
||||
void GetTypeInternal(nsAString& aType, const MutexAutoLock& aProofOfLock);
|
||||
|
||||
// FileBlobImpl has getter methods with lazy initialization. Because any
|
||||
// BlobImpl must work thread-safe, we use a mutex.
|
||||
// FileBlobImpl is the only BlobImpl with a few getter methods with lazy
|
||||
// initialization. Because any BlobImpl must work thread-safe, we use a mutex.
|
||||
// This is the list of the getter methods and the corresponding lazy members:
|
||||
// - GetMozFullPathInternal - mMozFullPath
|
||||
// - GetSize - mLength
|
||||
// - GetType - mContentType
|
||||
// - GetLastModified - mLastModificationDate
|
||||
Mutex mMutex;
|
||||
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
|
||||
nsString mContentType;
|
||||
nsString mName;
|
||||
nsString mPath; // The path relative to a directory chosen by the user
|
||||
nsString mMozFullPath;
|
||||
|
||||
const uint64_t mSerialNumber;
|
||||
uint64_t mStart;
|
||||
|
||||
int64_t mFileId;
|
||||
|
||||
Maybe<uint64_t> mLength;
|
||||
|
||||
Maybe<int64_t> mLastModified;
|
||||
|
||||
bool mIsFile;
|
||||
bool mWholeFile;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,25 +25,6 @@ NS_INTERFACE_MAP_BEGIN(MemoryBlobImpl::DataOwnerAdapter)
|
|||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
// static
|
||||
already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithCustomLastModified(
|
||||
void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
|
||||
const nsAString& aContentType, int64_t aLastModifiedDate) {
|
||||
RefPtr<MemoryBlobImpl> blobImpl = new MemoryBlobImpl(
|
||||
aMemoryBuffer, aLength, aName, aContentType, aLastModifiedDate);
|
||||
return blobImpl.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<MemoryBlobImpl> MemoryBlobImpl::CreateWithLastModifiedNow(
|
||||
void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
|
||||
const nsAString& aContentType) {
|
||||
int64_t lastModificationDate =
|
||||
nsRFPService::ReduceTimePrecisionAsUSecs(PR_Now(), 0);
|
||||
return CreateWithCustomLastModified(aMemoryBuffer, aLength, aName,
|
||||
aContentType, lastModificationDate);
|
||||
}
|
||||
|
||||
nsresult MemoryBlobImpl::DataOwnerAdapter::Create(DataOwner* aDataOwner,
|
||||
uint32_t aStart,
|
||||
uint32_t aLength,
|
||||
|
|
|
@ -23,18 +23,14 @@ class MemoryBlobImpl final : public BaseBlobImpl {
|
|||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(MemoryBlobImpl, BaseBlobImpl)
|
||||
|
||||
// File constructor.
|
||||
static already_AddRefed<MemoryBlobImpl> CreateWithLastModifiedNow(
|
||||
void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
|
||||
const nsAString& aContentType);
|
||||
MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
|
||||
const nsAString& aContentType, int64_t aLastModifiedDate)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MemoryBlobImpl"), aName, aContentType,
|
||||
aLength, aLastModifiedDate),
|
||||
mDataOwner(new DataOwner(aMemoryBuffer, aLength)) {
|
||||
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
|
||||
}
|
||||
|
||||
// File constructor with custom lastModified attribue value. You should
|
||||
// probably use CreateWithLastModifiedNow() instead of this one.
|
||||
static already_AddRefed<MemoryBlobImpl> CreateWithCustomLastModified(
|
||||
void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
|
||||
const nsAString& aContentType, int64_t aLastModifiedDate);
|
||||
|
||||
// Blob constructor.
|
||||
MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength,
|
||||
const nsAString& aContentType)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MemoryBlobImpl"), aContentType,
|
||||
|
@ -144,15 +140,6 @@ class MemoryBlobImpl final : public BaseBlobImpl {
|
|||
};
|
||||
|
||||
private:
|
||||
// File constructor.
|
||||
MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
|
||||
const nsAString& aContentType, int64_t aLastModifiedDate)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MemoryBlobImpl"), aName, aContentType,
|
||||
aLength, aLastModifiedDate),
|
||||
mDataOwner(new DataOwner(aMemoryBuffer, aLength)) {
|
||||
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
|
||||
}
|
||||
|
||||
// Create slice
|
||||
MemoryBlobImpl(const MemoryBlobImpl* aOther, uint64_t aStart,
|
||||
uint64_t aLength, const nsAString& aContentType)
|
||||
|
|
|
@ -232,9 +232,8 @@ void MultipartBlobImpl::InitializeBlob(const Sequence<Blob::BlobPart>& aData,
|
|||
}
|
||||
|
||||
void MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mLength == MULTIPARTBLOBIMPL_UNKNOWN_LENGTH);
|
||||
MOZ_ASSERT_IF(mIsFile, mLastModificationDate ==
|
||||
MULTIPARTBLOBIMPL_UNKNOWN_LAST_MODIFIED);
|
||||
MOZ_ASSERT(mLength == UINT64_MAX);
|
||||
MOZ_ASSERT(mLastModificationDate == INT64_MAX);
|
||||
|
||||
uint64_t totalLength = 0;
|
||||
int64_t lastModified = 0;
|
||||
|
@ -244,6 +243,11 @@ void MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv) {
|
|||
index++) {
|
||||
RefPtr<BlobImpl>& blob = mBlobImpls[index];
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!blob->IsSizeUnknown());
|
||||
MOZ_ASSERT(!blob->IsDateUnknown());
|
||||
#endif
|
||||
|
||||
uint64_t subBlobLength = blob->GetSize(aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
|
@ -325,7 +329,3 @@ void MultipartBlobImpl::GetBlobImplType(nsAString& aBlobImplType) const {
|
|||
|
||||
aBlobImplType.AppendLiteral("]");
|
||||
}
|
||||
|
||||
void MultipartBlobImpl::SetLastModified(int64_t aLastModified) {
|
||||
mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
|
||||
}
|
||||
|
|
|
@ -16,11 +16,6 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// This is just a sentinel value to be sure that we don't call
|
||||
// SetLengthAndModifiedDate more than once.
|
||||
constexpr int64_t MULTIPARTBLOBIMPL_UNKNOWN_LAST_MODIFIED = INT64_MAX;
|
||||
constexpr uint64_t MULTIPARTBLOBIMPL_UNKNOWN_LENGTH = UINT64_MAX;
|
||||
|
||||
class MultipartBlobImpl final : public BaseBlobImpl {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(MultipartBlobImpl, BaseBlobImpl)
|
||||
|
@ -38,13 +33,12 @@ class MultipartBlobImpl final : public BaseBlobImpl {
|
|||
// Create as a file to be later initialized
|
||||
explicit MultipartBlobImpl(const nsAString& aName)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
|
||||
EmptyString(), MULTIPARTBLOBIMPL_UNKNOWN_LENGTH,
|
||||
MULTIPARTBLOBIMPL_UNKNOWN_LAST_MODIFIED) {}
|
||||
EmptyString(), UINT64_MAX) {}
|
||||
|
||||
// Create as a blob to be later initialized
|
||||
MultipartBlobImpl()
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), EmptyString(),
|
||||
MULTIPARTBLOBIMPL_UNKNOWN_LENGTH) {}
|
||||
UINT64_MAX) {}
|
||||
|
||||
void InitializeBlob(ErrorResult& aRv);
|
||||
|
||||
|
@ -74,22 +68,17 @@ class MultipartBlobImpl final : public BaseBlobImpl {
|
|||
|
||||
void GetBlobImplType(nsAString& aBlobImplType) const override;
|
||||
|
||||
void SetLastModified(int64_t aLastModified);
|
||||
|
||||
protected:
|
||||
// File constructor.
|
||||
MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
|
||||
const nsAString& aName, const nsAString& aContentType)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aName,
|
||||
aContentType, MULTIPARTBLOBIMPL_UNKNOWN_LENGTH,
|
||||
MULTIPARTBLOBIMPL_UNKNOWN_LAST_MODIFIED),
|
||||
aContentType, UINT64_MAX),
|
||||
mBlobImpls(std::move(aBlobImpls)) {}
|
||||
|
||||
// Blob constructor.
|
||||
MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
|
||||
const nsAString& aContentType)
|
||||
: BaseBlobImpl(NS_LITERAL_STRING("MultipartBlobImpl"), aContentType,
|
||||
MULTIPARTBLOBIMPL_UNKNOWN_LENGTH),
|
||||
UINT64_MAX),
|
||||
mBlobImpls(std::move(aBlobImpls)) {}
|
||||
|
||||
virtual ~MultipartBlobImpl() = default;
|
||||
|
|
|
@ -20,13 +20,11 @@ class StreamBlobImpl final : public BaseBlobImpl, public nsIMemoryReporter {
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIMEMORYREPORTER
|
||||
|
||||
// Blob constructor.
|
||||
static already_AddRefed<StreamBlobImpl> Create(
|
||||
already_AddRefed<nsIInputStream> aInputStream,
|
||||
const nsAString& aContentType, uint64_t aLength,
|
||||
const nsAString& aBlobImplType);
|
||||
|
||||
// File constructor.
|
||||
static already_AddRefed<StreamBlobImpl> Create(
|
||||
already_AddRefed<nsIInputStream> aInputStream, const nsAString& aName,
|
||||
const nsAString& aContentType, int64_t aLastModifiedDate,
|
||||
|
@ -66,12 +64,10 @@ class StreamBlobImpl final : public BaseBlobImpl, public nsIMemoryReporter {
|
|||
void GetBlobImplType(nsAString& aBlobImplType) const override;
|
||||
|
||||
private:
|
||||
// Blob constructor.
|
||||
StreamBlobImpl(already_AddRefed<nsIInputStream> aInputStream,
|
||||
const nsAString& aContentType, uint64_t aLength,
|
||||
const nsAString& aBlobImplType);
|
||||
|
||||
// File constructor.
|
||||
StreamBlobImpl(already_AddRefed<nsIInputStream> aInputStream,
|
||||
const nsAString& aName, const nsAString& aContentType,
|
||||
int64_t aLastModifiedDate, uint64_t aLength,
|
||||
|
|
|
@ -96,7 +96,8 @@ class TemporaryFileInputStream final : public nsFileInputStream {
|
|||
|
||||
TemporaryFileBlobImpl::TemporaryFileBlobImpl(nsIFile* aFile,
|
||||
const nsAString& aContentType)
|
||||
: FileBlobImpl(aFile, EmptyString(), aContentType)
|
||||
: FileBlobImpl(aFile, EmptyString(), aContentType,
|
||||
NS_LITERAL_STRING("TemporaryBlobImpl"))
|
||||
#ifdef DEBUG
|
||||
,
|
||||
mInputStreamCreated(false)
|
||||
|
|
|
@ -30,10 +30,6 @@ class TemporaryFileBlobImpl final : public FileBlobImpl {
|
|||
virtual void CreateInputStream(nsIInputStream** aInputStream,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
void GetBlobImplType(nsAString& aBlobImplType) const override {
|
||||
aBlobImplType = NS_LITERAL_STRING("TemporaryFileBlobImpl");
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~TemporaryFileBlobImpl();
|
||||
|
||||
|
|
|
@ -893,8 +893,8 @@ nsresult HTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName,
|
|||
do_QueryInterface(OwnerDoc()->GetScopeObject());
|
||||
|
||||
// The File takes ownership of the buffer
|
||||
RefPtr<File> file = File::CreateMemoryFileWithLastModifiedNow(
|
||||
win->AsGlobal(), imgData, imgSize, aName, type);
|
||||
RefPtr<File> file = File::CreateMemoryFile(win->AsGlobal(), imgData, imgSize,
|
||||
aName, type, PR_Now());
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче