Backed out changeset 61101e3eebb3 (bug 1030481) for mochitest failures at test_file.xhtml. CLOSED TREE

This commit is contained in:
Brindusan Cristian 2020-01-07 16:30:53 +02:00
parent 9060dd6a5d
commit ed883ce3f4
20 changed files with 169 additions and 46 deletions

View File

@ -464,6 +464,8 @@ JSObject* ReadBlob(JSContext* aCx, uint32_t aIndex,
// pointer while destructors are running.
RefPtr<BlobImpl> blobImpl = aHolder->BlobImpls()[aIndex];
MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false));
RefPtr<Blob> blob = Blob::Create(aHolder->GlobalDuringRead(), blobImpl);
if (NS_WARN_IF(!blob)) {
return nullptr;
@ -490,6 +492,7 @@ bool WriteBlob(JSStructuredCloneWriter* aWriter, Blob* aBlob,
}
RefPtr<BlobImpl> blobImpl = aBlob->Impl();
MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false));
// We store the position of the blobImpl in the array as index.
if (JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
@ -601,6 +604,8 @@ JSObject* ReadFileList(JSContext* aCx, JSStructuredCloneReader* aReader,
RefPtr<BlobImpl> blobImpl = aHolder->BlobImpls()[pos];
MOZ_ASSERT(blobImpl->IsFile());
MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false));
RefPtr<File> file = File::Create(aHolder->GlobalDuringRead(), blobImpl);
if (NS_WARN_IF(!file)) {
return nullptr;
@ -640,6 +645,7 @@ bool WriteFileList(JSStructuredCloneWriter* aWriter, FileList* aFileList,
for (uint32_t i = 0; i < aFileList->Length(); ++i) {
RefPtr<BlobImpl> blobImpl = aFileList->Item(i)->Impl();
MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false));
blobImpls.AppendElement(blobImpl);
}
@ -680,6 +686,7 @@ JSObject* ReadFormData(JSContext* aCx, JSStructuredCloneReader* aReader,
MOZ_ASSERT(indexOrLengthOfString < aHolder->BlobImpls().Length());
RefPtr<BlobImpl> blobImpl = aHolder->BlobImpls()[indexOrLengthOfString];
MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false));
RefPtr<Blob> blob = Blob::Create(aHolder->GlobalDuringRead(), blobImpl);
if (NS_WARN_IF(!blob)) {
@ -778,6 +785,7 @@ bool WriteFormData(JSStructuredCloneWriter* aWriter, FormData* aFormData,
}
RefPtr<BlobImpl> blobImpl = aValue.GetAsBlob()->Impl();
MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false));
closure->mHolder->BlobImpls().AppendElement(blobImpl);
return true;

View File

@ -98,6 +98,32 @@ nsresult BaseBlobImpl::GetSendInfo(nsIInputStream** aBody,
return NS_OK;
}
nsresult BaseBlobImpl::GetMutable(bool* aMutable) const {
*aMutable = !mImmutable;
return NS_OK;
}
nsresult BaseBlobImpl::SetMutable(bool aMutable) {
nsresult rv = NS_OK;
NS_ENSURE_ARG(!mImmutable || !aMutable);
if (!mImmutable && !aMutable) {
// Force the content type and size to be cached
nsAutoString dummyString;
GetType(dummyString);
ErrorResult error;
GetSize(error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
mImmutable = !aMutable;
return rv;
}
/* static */
uint64_t BaseBlobImpl::NextSerialNumber() {
static Atomic<uint64_t> nextSerialNumber;

View File

@ -19,6 +19,7 @@ class BaseBlobImpl : public BlobImpl {
int64_t aLastModifiedDate)
: mBlobImplType(aBlobImplType),
mIsFile(true),
mImmutable(false),
mContentType(aContentType),
mName(aName),
mStart(0),
@ -33,6 +34,7 @@ class BaseBlobImpl : public BlobImpl {
const nsAString& aContentType, uint64_t aLength)
: mBlobImplType(aBlobImplType),
mIsFile(true),
mImmutable(false),
mContentType(aContentType),
mName(aName),
mStart(0),
@ -47,6 +49,7 @@ class BaseBlobImpl : public BlobImpl {
uint64_t aLength)
: mBlobImplType(aBlobImplType),
mIsFile(false),
mImmutable(false),
mContentType(aContentType),
mStart(0),
mLength(aLength),
@ -60,6 +63,7 @@ class BaseBlobImpl : public BlobImpl {
uint64_t aStart, uint64_t aLength)
: mBlobImplType(aBlobImplType),
mIsFile(false),
mImmutable(false),
mContentType(aContentType),
mStart(aStart),
mLength(aLength),
@ -122,6 +126,10 @@ class BaseBlobImpl : public BlobImpl {
nsACString& aContentType,
nsACString& aCharset) override;
virtual nsresult GetMutable(bool* aMutable) const override;
virtual nsresult SetMutable(bool aMutable) override;
virtual void SetLazyData(const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
int64_t aLastModifiedDate) override {
@ -159,6 +167,7 @@ class BaseBlobImpl : public BlobImpl {
const nsString mBlobImplType;
bool mIsFile;
bool mImmutable;
nsString mContentType;
nsString mName;

View File

@ -40,8 +40,9 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutable)
NS_INTERFACE_MAP_ENTRY_CONCRETE(Blob)
NS_INTERFACE_MAP_ENTRY(nsIMutable)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END
@ -205,6 +206,12 @@ nsresult Blob::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
}
NS_IMETHODIMP
Blob::GetMutable(bool* aMutable) { return mImpl->GetMutable(aMutable); }
NS_IMETHODIMP
Blob::SetMutable(bool aMutable) { return mImpl->SetMutable(aMutable); }
JSObject* Blob::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
return Blob_Binding::Wrap(aCx, this, aGivenProto);
}

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/BodyConsumer.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
#include "nsIMutable.h"
#include "nsWrapperCache.h"
#include "nsWeakReference.h"
@ -35,11 +36,14 @@ class Promise;
} \
}
class Blob : public nsSupportsWeakReference,
class Blob : public nsIMutable,
public nsSupportsWeakReference,
public nsWrapperCache {
public:
NS_DECL_NSIMUTABLE
NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Blob)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIMutable)
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_BLOB_IID)
typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
@ -154,7 +158,7 @@ size_t BindingJSObjectMallocBytes(Blob* aBlob);
} // namespace mozilla
inline nsISupports* ToSupports(mozilla::dom::Blob* aBlob) {
return static_cast<nsISupportsWeakReference*>(aBlob);
return static_cast<nsIMutable*>(aBlob);
}
#endif // mozilla_dom_Blob_h

View File

@ -89,6 +89,10 @@ class BlobImpl : public nsISupports {
nsACString& aContentType,
nsACString& aCharset) = 0;
virtual nsresult GetMutable(bool* aMutable) const = 0;
virtual nsresult SetMutable(bool aMutable) = 0;
virtual void SetLazyData(const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
int64_t aLastModifiedDate) = 0;

View File

@ -15,6 +15,11 @@ already_AddRefed<BlobImpl> EmptyBlobImpl::CreateSlice(
ErrorResult& aRv) {
MOZ_ASSERT(!aStart && !aLength);
RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
DebugOnly<bool> isMutable;
MOZ_ASSERT(NS_SUCCEEDED(impl->GetMutable(&isMutable)));
MOZ_ASSERT(!isMutable);
return impl.forget();
}

View File

@ -18,12 +18,16 @@ class EmptyBlobImpl final : public BaseBlobImpl {
explicit EmptyBlobImpl(const nsAString& aContentType)
: BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aContentType,
0 /* aLength */) {}
0 /* aLength */) {
mImmutable = true;
}
EmptyBlobImpl(const nsAString& aName, const nsAString& aContentType,
int64_t aLastModifiedDate)
: BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aName, aContentType, 0,
aLastModifiedDate) {}
aLastModifiedDate) {
mImmutable = true;
}
virtual void CreateInputStream(nsIInputStream** aStream,
ErrorResult& aRv) override;

View File

@ -21,7 +21,6 @@ namespace dom {
FileBlobImpl::FileBlobImpl(nsIFile* aFile)
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), EmptyString(),
EmptyString(), UINT64_MAX, INT64_MAX),
mMutex("FileBlobImpl::mMutex"),
mFile(aFile),
mFileId(-1),
mWholeFile(true) {
@ -38,7 +37,6 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName,
nsIFile* aFile)
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
aLength, UINT64_MAX),
mMutex("FileBlobImpl::mMutex"),
mFile(aFile),
mFileId(-1),
mWholeFile(true) {
@ -52,7 +50,6 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName,
nsIFile* aFile, int64_t aLastModificationDate)
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType,
aLength, aLastModificationDate),
mMutex("FileBlobImpl::mMutex"),
mFile(aFile),
mFileId(-1),
mWholeFile(true) {
@ -65,7 +62,6 @@ FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
const nsAString& aContentType,
const nsAString& aBlobImplType)
: BaseBlobImpl(aBlobImplType, aName, aContentType, UINT64_MAX, INT64_MAX),
mMutex("FileBlobImpl::mMutex"),
mFile(aFile),
mFileId(-1),
mWholeFile(true) {
@ -83,12 +79,12 @@ FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
uint64_t aLength, const nsAString& aContentType)
: BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aContentType,
aOther->mStart + aStart, aLength),
mMutex("FileBlobImpl::mMutex"),
mFile(aOther->mFile),
mFileId(-1),
mWholeFile(false) {
MOZ_ASSERT(mFile, "must have file");
MOZ_ASSERT(XRE_IsParentProcess());
mImmutable = aOther->mImmutable;
mMozFullPath = aOther->mMozFullPath;
}
@ -104,8 +100,6 @@ void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
ErrorResult& aRv) {
MOZ_ASSERT(mIsFile, "Should only be called on files");
MutexAutoLock lock(mMutex);
if (!mMozFullPath.IsVoid()) {
aFilename = mMozFullPath;
return;
@ -120,8 +114,6 @@ void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
}
uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) {
MutexAutoLock lock(mMutex);
if (BaseBlobImpl::IsSizeUnknown()) {
MOZ_ASSERT(mWholeFile,
"Should only use lazy size when using the whole file");
@ -142,14 +134,14 @@ uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) {
return mLength;
}
class FileBlobImpl::GetTypeRunnable final : public WorkerMainThreadRunnable {
namespace {
class GetTypeRunnable final : public WorkerMainThreadRunnable {
public:
GetTypeRunnable(WorkerPrivate* aWorkerPrivate, FileBlobImpl* aBlobImpl,
const MutexAutoLock& aProofOfLock)
GetTypeRunnable(WorkerPrivate* aWorkerPrivate, BlobImpl* aBlobImpl)
: WorkerMainThreadRunnable(aWorkerPrivate,
NS_LITERAL_CSTRING("FileBlobImpl :: GetType")),
mBlobImpl(aBlobImpl),
mProofOfLock(aProofOfLock) {
mBlobImpl(aBlobImpl) {
MOZ_ASSERT(aBlobImpl);
aWorkerPrivate->AssertIsOnWorkerThread();
}
@ -158,24 +150,19 @@ class FileBlobImpl::GetTypeRunnable final : public WorkerMainThreadRunnable {
MOZ_ASSERT(NS_IsMainThread());
nsAutoString type;
mBlobImpl->GetTypeInternal(type, mProofOfLock);
mBlobImpl->GetType(type);
return true;
}
private:
~GetTypeRunnable() = default;
RefPtr<FileBlobImpl> mBlobImpl;
const MutexAutoLock& mProofOfLock;
RefPtr<BlobImpl> mBlobImpl;
};
void FileBlobImpl::GetType(nsAString& aType) {
MutexAutoLock lock(mMutex);
GetTypeInternal(aType, lock);
}
} // anonymous namespace
void FileBlobImpl::GetTypeInternal(nsAString& aType,
const MutexAutoLock& aProofOfLock) {
void FileBlobImpl::GetType(nsAString& aType) {
aType.Truncate();
if (mContentType.IsVoid()) {
@ -191,7 +178,7 @@ void FileBlobImpl::GetTypeInternal(nsAString& aType,
}
RefPtr<GetTypeRunnable> runnable =
new GetTypeRunnable(workerPrivate, this, aProofOfLock);
new GetTypeRunnable(workerPrivate, this);
ErrorResult rv;
runnable->Dispatch(Canceling, rv);
@ -223,9 +210,6 @@ void FileBlobImpl::GetTypeInternal(nsAString& aType,
int64_t FileBlobImpl::GetLastModified(ErrorResult& aRv) {
MOZ_ASSERT(mIsFile, "Should only be called on files");
MutexAutoLock lock(mMutex);
if (BaseBlobImpl::IsDateUnknown()) {
PRTime msecs;
aRv = mFile->GetLastModifiedTime(&msecs);

View File

@ -8,7 +8,6 @@
#define mozilla_dom_FileBlobImpl_h
#include "mozilla/dom/BaseBlobImpl.h"
#include "mozilla/Mutex.h"
class nsIFile;
@ -73,18 +72,6 @@ class FileBlobImpl : public BaseBlobImpl {
const nsAString& aContentType,
ErrorResult& aRv) override;
class GetTypeRunnable;
void GetTypeInternal(nsAString& aType, const MutexAutoLock& aProofOfLock);
// 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 mMozFullPath;
int64_t mFileId;

View File

@ -147,6 +147,7 @@ class MemoryBlobImpl final : public BaseBlobImpl {
aOther->mStart + aStart, aLength),
mDataOwner(aOther->mDataOwner) {
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
mImmutable = aOther->mImmutable;
}
~MemoryBlobImpl() {}

View File

@ -283,6 +283,33 @@ void MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv) {
}
}
nsresult MultipartBlobImpl::SetMutable(bool aMutable) {
nsresult rv;
// This looks a little sketchy since BlobImpl objects are supposed to be
// threadsafe. However, we try to enforce that all BlobImpl objects must be
// set to immutable *before* being passed to another thread, so this should
// be safe.
if (!aMutable && !mImmutable && !mBlobImpls.IsEmpty()) {
for (uint32_t index = 0, count = mBlobImpls.Length(); index < count;
index++) {
rv = mBlobImpls[index]->SetMutable(aMutable);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
}
rv = BaseBlobImpl::SetMutable(aMutable);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT_IF(!aMutable, mImmutable);
return NS_OK;
}
bool MultipartBlobImpl::MayBeClonedToOtherThreads() const {
for (uint32_t i = 0; i < mBlobImpls.Length(); ++i) {
if (!mBlobImpls[i]->MayBeClonedToOtherThreads()) {

View File

@ -59,6 +59,8 @@ class MultipartBlobImpl final : public BaseBlobImpl {
return mBlobImpls.Length() ? &mBlobImpls : nullptr;
}
virtual nsresult SetMutable(bool aMutable) override;
void SetName(const nsAString& aName) { mName = aName; }
virtual bool MayBeClonedToOtherThreads() const override;

View File

@ -51,6 +51,7 @@ StreamBlobImpl::StreamBlobImpl(already_AddRefed<nsIInputStream> aInputStream,
mInputStream(std::move(aInputStream)),
mIsDirectory(false),
mFileId(-1) {
mImmutable = true;
}
StreamBlobImpl::StreamBlobImpl(already_AddRefed<nsIInputStream> aInputStream,
@ -63,6 +64,7 @@ StreamBlobImpl::StreamBlobImpl(already_AddRefed<nsIInputStream> aInputStream,
mInputStream(std::move(aInputStream)),
mIsDirectory(false),
mFileId(-1) {
mImmutable = true;
}
StreamBlobImpl::~StreamBlobImpl() { UnregisterWeakMemoryReporter(this); }

View File

@ -123,6 +123,14 @@ class BlobImplSnapshot final : public BlobImpl, public PIBlobImplSnapshot {
aCharset);
}
virtual nsresult GetMutable(bool* aMutable) const override {
return mBlobImpl->GetMutable(aMutable);
}
virtual nsresult SetMutable(bool aMutable) override {
return mBlobImpl->SetMutable(aMutable);
}
virtual void SetLazyData(const nsAString& aName,
const nsAString& aContentType, uint64_t aLength,
int64_t aLastModifiedDate) override {

View File

@ -29,6 +29,10 @@ class CreateURLRunnable : public WorkerMainThreadRunnable {
mBlobImpl(aBlobImpl),
mURL(aURL) {
MOZ_ASSERT(aBlobImpl);
DebugOnly<bool> isMutable;
MOZ_ASSERT(NS_SUCCEEDED(aBlobImpl->GetMutable(&isMutable)));
MOZ_ASSERT(!isMutable);
}
bool MainThreadRun() override {
@ -36,6 +40,10 @@ class CreateURLRunnable : public WorkerMainThreadRunnable {
AssertIsOnMainThread();
DebugOnly<bool> isMutable;
MOZ_ASSERT(NS_SUCCEEDED(mBlobImpl->GetMutable(&isMutable)));
MOZ_ASSERT(!isMutable);
nsCOMPtr<nsIPrincipal> principal = mWorkerPrivate->GetPrincipal();
nsAutoCString url;
@ -155,6 +163,11 @@ void URLWorker::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
RefPtr<BlobImpl> blobImpl = aBlob.Impl();
MOZ_ASSERT(blobImpl);
aRv = blobImpl->SetMutable(false);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
RefPtr<CreateURLRunnable> runnable =
new CreateURLRunnable(workerPrivate, blobImpl, aResult);

View File

@ -1893,6 +1893,14 @@ void XMLHttpRequestWorker::Send(
RefPtr<Blob> blob = &aData.Value().GetAsBlob();
MOZ_ASSERT(blob);
RefPtr<BlobImpl> blobImpl = blob->Impl();
MOZ_ASSERT(blobImpl);
aRv = blobImpl->SetMutable(false);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
JS::Rooted<JS::Value> value(aCx);
if (!GetOrCreateDOMReflector(aCx, blob, &value)) {
aRv.Throw(NS_ERROR_FAILURE);

View File

@ -18,6 +18,7 @@ XPIDL_SOURCES += [
'nsIMemoryInfoDumper.idl',
'nsIMemoryReporter.idl',
'nsIMessageLoop.idl',
'nsIMutable.idl',
'nsISecurityConsoleMessage.idl',
'nsISupports.idl',
'nsIUUIDGenerator.idl',

22
xpcom/base/nsIMutable.idl Normal file
View File

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/**
* nsIMutable defines an interface to be implemented by objects which
* can be made immutable.
*/
[scriptable, uuid(321578d0-03c1-4d95-8821-021ac612d18d)]
interface nsIMutable : nsISupports
{
/**
* Control whether or not this object can be modified. If the flag is
* false, no modification is allowed. Once the flag has been set to false,
* it cannot be reset back to true -- attempts to do so throw
* NS_ERROR_INVALID_ARG.
*/
attribute boolean mutable;
};

View File

@ -77,6 +77,7 @@
#include "nsIInputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsILineInputStream.h"
#include "nsIMutable.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIOutputStream.h"