Dactyloidae/dom/indexedDB/IDBFileHandle.cpp
Martok f059bb0a59 Issue #2240 - Align Microtasks and promises scheduling with spec
Microtasks, resolved Promises and Observers are handled after the sync
task that caused them, in the order they were generated.
Also simplifies reentrancy handling.

Based-on: m-c 1193394
2024-01-09 11:59:32 +08:00

200 lines
5 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "IDBFileHandle.h"
#include "IDBEvents.h"
#include "IDBMutableFile.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/IDBFileHandleBinding.h"
#include "mozilla/dom/filehandle/ActorsChild.h"
#include "mozilla/EventDispatcher.h"
#include "nsContentUtils.h"
#include "nsQueryObject.h"
#include "nsServiceManagerUtils.h"
#include "nsWidgetsCID.h"
namespace mozilla {
namespace dom {
using namespace mozilla::dom::indexedDB;
IDBFileHandle::IDBFileHandle(FileMode aMode,
IDBMutableFile* aMutableFile)
: FileHandleBase(DEBUGONLY(aMutableFile->OwningThread(),)
aMode)
, mMutableFile(aMutableFile)
{
AssertIsOnOwningThread();
}
IDBFileHandle::~IDBFileHandle()
{
AssertIsOnOwningThread();
mMutableFile->UnregisterFileHandle(this);
}
// static
already_AddRefed<IDBFileHandle>
IDBFileHandle::Create(IDBMutableFile* aMutableFile,
FileMode aMode)
{
MOZ_ASSERT(aMutableFile);
aMutableFile->AssertIsOnOwningThread();
MOZ_ASSERT(aMode == FileMode::Readonly || aMode == FileMode::Readwrite);
RefPtr<IDBFileHandle> fileHandle =
new IDBFileHandle(aMode, aMutableFile);
fileHandle->BindToOwner(aMutableFile);
// XXX Fix!
MOZ_ASSERT(NS_IsMainThread(), "This won't work on non-main threads!");
nsCOMPtr<nsIRunnable> runnable = do_QueryObject(fileHandle);
nsContentUtils::AddPendingIDBTransaction(runnable.forget());
fileHandle->SetCreating();
aMutableFile->RegisterFileHandle(fileHandle);
return fileHandle.forget();
}
already_AddRefed<IDBFileRequest>
IDBFileHandle::GetMetadata(const IDBFileMetadataParameters& aParameters,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
// Common state checking
if (!CheckState(aRv)) {
return nullptr;
}
// Argument checking for get metadata.
if (!aParameters.mSize && !aParameters.mLastModified) {
aRv.ThrowTypeError<MSG_METADATA_NOT_CONFIGURED>();
return nullptr;
}
// Do nothing if the window is closed
if (!CheckWindow()) {
return nullptr;
}
FileRequestGetMetadataParams params;
params.size() = aParameters.mSize;
params.lastModified() = aParameters.mLastModified;
RefPtr<FileRequestBase> fileRequest = GenerateFileRequest();
StartRequest(fileRequest, params);
return fileRequest.forget().downcast<IDBFileRequest>();
}
NS_IMPL_ADDREF_INHERITED(IDBFileHandle, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IDBFileHandle, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBFileHandle)
NS_INTERFACE_MAP_ENTRY(nsIRunnable)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFileHandle)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBFileHandle,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMutableFile)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBFileHandle,
DOMEventTargetHelper)
// Don't unlink mMutableFile!
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMETHODIMP
IDBFileHandle::Run()
{
AssertIsOnOwningThread();
OnReturnToEventLoop();
return NS_OK;
}
nsresult
IDBFileHandle::GetEventTargetParent(EventChainPreVisitor& aVisitor)
{
AssertIsOnOwningThread();
aVisitor.mCanHandle = true;
aVisitor.SetParentTarget(mMutableFile, false);
return NS_OK;
}
// virtual
JSObject*
IDBFileHandle::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
AssertIsOnOwningThread();
return IDBFileHandleBinding::Wrap(aCx, this, aGivenProto);
}
mozilla::dom::MutableFileBase*
IDBFileHandle::MutableFile() const
{
AssertIsOnOwningThread();
return mMutableFile;
}
void
IDBFileHandle::HandleCompleteOrAbort(bool aAborted)
{
AssertIsOnOwningThread();
FileHandleBase::HandleCompleteOrAbort(aAborted);
nsCOMPtr<nsIDOMEvent> event;
if (aAborted) {
event = CreateGenericEvent(this, nsDependentString(kAbortEventType),
eDoesBubble, eNotCancelable);
} else {
event = CreateGenericEvent(this, nsDependentString(kCompleteEventType),
eDoesNotBubble, eNotCancelable);
}
if (NS_WARN_IF(!event)) {
return;
}
bool dummy;
if (NS_FAILED(DispatchEvent(event, &dummy))) {
NS_WARNING("DispatchEvent failed!");
}
}
bool
IDBFileHandle::CheckWindow()
{
AssertIsOnOwningThread();
return GetOwner();
}
already_AddRefed<mozilla::dom::FileRequestBase>
IDBFileHandle::GenerateFileRequest()
{
AssertIsOnOwningThread();
return IDBFileRequest::Create(GetOwner(), this,
/* aWrapAsDOMRequest */ false);
}
} // namespace dom
} // namespace mozilla