2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2014-09-27 03:21:57 +04:00
|
|
|
/* 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/. */
|
|
|
|
|
2020-03-28 16:35:31 +03:00
|
|
|
#include <type_traits>
|
|
|
|
|
2021-11-08 11:14:00 +03:00
|
|
|
#include "ActorsChild.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "BackgroundChildImpl.h"
|
|
|
|
#include "IDBDatabase.h"
|
|
|
|
#include "IDBEvents.h"
|
|
|
|
#include "IDBFactory.h"
|
2017-06-07 13:36:42 +03:00
|
|
|
#include "IDBFileHandle.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "IDBIndex.h"
|
2015-09-09 14:15:05 +03:00
|
|
|
#include "IDBMutableFile.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "IDBObjectStore.h"
|
|
|
|
#include "IDBRequest.h"
|
|
|
|
#include "IDBTransaction.h"
|
|
|
|
#include "IndexedDatabase.h"
|
|
|
|
#include "IndexedDatabaseInlines.h"
|
2020-09-07 18:52:52 +03:00
|
|
|
#include "IndexedDBCommon.h"
|
2021-07-13 14:52:42 +03:00
|
|
|
#include "js/Array.h" // JS::NewArrayObject, JS::SetArrayLength
|
|
|
|
#include "js/Date.h" // JS::NewDateObject, JS::TimeClip
|
|
|
|
#include "js/PropertyAndElement.h" // JS_DefineElement, JS_DefineProperty
|
2020-06-29 14:02:53 +03:00
|
|
|
#include <mozIRemoteLazyInputStream.h>
|
2020-04-21 17:35:03 +03:00
|
|
|
#include "mozilla/ArrayAlgorithm.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/BasicEvents.h"
|
2017-02-24 00:23:45 +03:00
|
|
|
#include "mozilla/CycleCollectedJSRuntime.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/Maybe.h"
|
2020-09-07 18:52:52 +03:00
|
|
|
#include "mozilla/ResultExtensions.h"
|
2020-11-23 19:21:38 +03:00
|
|
|
#include "mozilla/dom/BlobImpl.h"
|
2015-04-10 19:10:00 +03:00
|
|
|
#include "mozilla/dom/Element.h"
|
2018-04-20 19:53:17 +03:00
|
|
|
#include "mozilla/dom/Event.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
2019-04-10 01:39:01 +03:00
|
|
|
#include "mozilla/dom/BrowserChild.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseFileChild.h"
|
2017-05-23 08:50:33 +03:00
|
|
|
#include "mozilla/dom/IPCBlobUtils.h"
|
2018-01-31 10:25:30 +03:00
|
|
|
#include "mozilla/dom/WorkerPrivate.h"
|
|
|
|
#include "mozilla/dom/WorkerRunnable.h"
|
2021-11-30 08:05:51 +03:00
|
|
|
#include "mozilla/dom/quota/ResultExtensions.h"
|
2017-06-16 15:11:03 +03:00
|
|
|
#include "mozilla/Encoding.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/ipc/BackgroundUtils.h"
|
Bug 1691589 - Reduce reliance on GeckoProfiler.h when only labels (and maybe markers) are needed - r=necko-reviewers,geckoview-reviewers,sg,agi,florian
There are no code changes, only #include changes.
It was a fairly mechanical process: Search for all "AUTO_PROFILER_LABEL", and in each file, if only labels are used, convert "GeckoProfiler.h" into "ProfilerLabels.h" (or just add that last one where needed).
In some files, there were also some marker calls but no other profiler-related calls, in these cases "GeckoProfiler.h" was replaced with both "ProfilerLabels.h" and "ProfilerMarkers.h", which still helps in reducing the use of the all-encompassing "GeckoProfiler.h".
Differential Revision: https://phabricator.services.mozilla.com/D104588
2021-02-16 07:44:19 +03:00
|
|
|
#include "mozilla/ProfilerLabels.h"
|
2017-05-23 08:52:47 +03:00
|
|
|
#include "mozilla/TaskQueue.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsContentUtils.h"
|
2017-05-23 08:52:47 +03:00
|
|
|
#include "nsIAsyncInputStream.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsIEventTarget.h"
|
2016-10-25 22:19:06 +03:00
|
|
|
#include "nsIFileStreams.h"
|
|
|
|
#include "nsNetCID.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include "nsTraceRefcnt.h"
|
|
|
|
#include "PermissionRequestBase.h"
|
|
|
|
#include "ProfilerHelpers.h"
|
|
|
|
#include "ReportInternalError.h"
|
2020-07-03 12:40:12 +03:00
|
|
|
#include "ThreadLocal.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
# include "IndexedDatabaseManager.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define GC_ON_IPC_MESSAGES 0
|
|
|
|
|
|
|
|
#if defined(DEBUG) || GC_ON_IPC_MESSAGES
|
|
|
|
|
|
|
|
# include "js/GCAPI.h"
|
|
|
|
# include "nsJSEnvironment.h"
|
|
|
|
|
|
|
|
# define BUILD_GC_ON_IPC_MESSAGES
|
|
|
|
|
|
|
|
#endif // DEBUG || GC_ON_IPC_MESSAGES
|
|
|
|
|
|
|
|
namespace mozilla {
|
2015-05-06 11:07:57 +03:00
|
|
|
|
|
|
|
using ipc::PrincipalInfo;
|
|
|
|
|
2020-11-04 20:04:01 +03:00
|
|
|
namespace dom::indexedDB {
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2014-10-16 08:56:52 +04:00
|
|
|
/*******************************************************************************
|
|
|
|
* ThreadLocal
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
ThreadLocal::ThreadLocal(const nsID& aBackgroundChildLoggingId)
|
2020-07-03 12:40:12 +03:00
|
|
|
: mLoggingInfo(aBackgroundChildLoggingId, 1, -1, 1),
|
|
|
|
mLoggingIdString(aBackgroundChildLoggingId) {
|
2014-10-16 08:56:52 +04:00
|
|
|
MOZ_COUNT_CTOR(mozilla::dom::indexedDB::ThreadLocal);
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadLocal::~ThreadLocal() {
|
|
|
|
MOZ_COUNT_DTOR(mozilla::dom::indexedDB::ThreadLocal);
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
/*******************************************************************************
|
|
|
|
* Helpers
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
void MaybeCollectGarbageOnIPCMessage() {
|
|
|
|
#ifdef BUILD_GC_ON_IPC_MESSAGES
|
|
|
|
static const bool kCollectGarbageOnIPCMessages =
|
|
|
|
# if GC_ON_IPC_MESSAGES
|
|
|
|
true;
|
|
|
|
# else
|
|
|
|
false;
|
|
|
|
# endif // GC_ON_IPC_MESSAGES
|
|
|
|
|
|
|
|
if (!kCollectGarbageOnIPCMessages) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool haveWarnedAboutGC = false;
|
|
|
|
static bool haveWarnedAboutNonMainThread = false;
|
|
|
|
|
|
|
|
if (!haveWarnedAboutGC) {
|
|
|
|
haveWarnedAboutGC = true;
|
|
|
|
NS_WARNING("IndexedDB child actor GC debugging enabled!");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
if (!haveWarnedAboutNonMainThread) {
|
|
|
|
haveWarnedAboutNonMainThread = true;
|
|
|
|
NS_WARNING("Don't know how to GC on a non-main thread yet.");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-01-21 16:09:12 +03:00
|
|
|
nsJSContext::GarbageCollectNow(JS::GCReason::DOM_IPC);
|
2021-10-14 21:15:40 +03:00
|
|
|
nsJSContext::CycleCollectNow(CCReason::API);
|
2014-09-27 03:21:57 +04:00
|
|
|
#endif // BUILD_GC_ON_IPC_MESSAGES
|
|
|
|
}
|
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class MOZ_STACK_CLASS AutoSetCurrentTransaction final {
|
2021-08-16 20:05:41 +03:00
|
|
|
using BackgroundChildImpl = mozilla::ipc::BackgroundChildImpl;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
Maybe<IDBTransaction&> const mTransaction;
|
|
|
|
Maybe<IDBTransaction&> mPreviousTransaction;
|
2014-10-16 08:56:52 +04:00
|
|
|
ThreadLocal* mThreadLocal;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
public:
|
2019-12-04 15:59:09 +03:00
|
|
|
AutoSetCurrentTransaction(const AutoSetCurrentTransaction&) = delete;
|
|
|
|
AutoSetCurrentTransaction(AutoSetCurrentTransaction&&) = delete;
|
|
|
|
AutoSetCurrentTransaction& operator=(const AutoSetCurrentTransaction&) =
|
|
|
|
delete;
|
|
|
|
AutoSetCurrentTransaction& operator=(AutoSetCurrentTransaction&&) = delete;
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
explicit AutoSetCurrentTransaction(Maybe<IDBTransaction&> aTransaction)
|
2014-09-27 03:21:57 +04:00
|
|
|
: mTransaction(aTransaction),
|
2020-04-21 17:32:51 +03:00
|
|
|
mPreviousTransaction(),
|
2014-10-16 08:56:52 +04:00
|
|
|
mThreadLocal(nullptr) {
|
2014-09-27 03:21:57 +04:00
|
|
|
if (aTransaction) {
|
|
|
|
BackgroundChildImpl::ThreadLocal* threadLocal =
|
|
|
|
BackgroundChildImpl::GetThreadLocalForCurrentThread();
|
|
|
|
MOZ_ASSERT(threadLocal);
|
|
|
|
|
2014-10-16 08:56:52 +04:00
|
|
|
// Hang onto this for resetting later.
|
2020-02-24 22:26:40 +03:00
|
|
|
mThreadLocal = threadLocal->mIndexedDBThreadLocal.get();
|
2014-10-16 08:56:52 +04:00
|
|
|
MOZ_ASSERT(mThreadLocal);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
// Save the current value.
|
2020-04-21 17:32:51 +03:00
|
|
|
mPreviousTransaction = mThreadLocal->MaybeCurrentTransactionRef();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
// Set the new value.
|
2014-10-16 08:56:52 +04:00
|
|
|
mThreadLocal->SetCurrentTransaction(aTransaction);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~AutoSetCurrentTransaction() {
|
2014-10-16 08:56:52 +04:00
|
|
|
MOZ_ASSERT_IF(mThreadLocal, mTransaction);
|
|
|
|
MOZ_ASSERT_IF(mThreadLocal,
|
2020-04-21 17:32:51 +03:00
|
|
|
ReferenceEquals(mThreadLocal->MaybeCurrentTransactionRef(),
|
|
|
|
mTransaction));
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2014-10-16 08:56:52 +04:00
|
|
|
if (mThreadLocal) {
|
2014-09-27 03:21:57 +04:00
|
|
|
// Reset old value.
|
2014-10-16 08:56:52 +04:00
|
|
|
mThreadLocal->SetCurrentTransaction(mPreviousTransaction);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
template <typename T>
|
|
|
|
void SetResultAndDispatchSuccessEvent(
|
2020-07-01 23:14:23 +03:00
|
|
|
const NotNull<RefPtr<IDBRequest>>& aRequest,
|
|
|
|
const SafeRefPtr<IDBTransaction>& aTransaction, T& aPtr,
|
2020-05-14 12:42:23 +03:00
|
|
|
RefPtr<Event> aEvent = nullptr);
|
|
|
|
|
|
|
|
namespace detail {
|
2020-07-01 23:14:23 +03:00
|
|
|
void DispatchSuccessEvent(const NotNull<RefPtr<IDBRequest>>& aRequest,
|
2020-05-14 12:42:23 +03:00
|
|
|
const SafeRefPtr<IDBTransaction>& aTransaction,
|
|
|
|
const RefPtr<Event>& aEvent);
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
std::enable_if_t<std::is_same_v<T, IDBDatabase> ||
|
|
|
|
std::is_same_v<T, IDBCursor> ||
|
|
|
|
std::is_same_v<T, IDBMutableFile>,
|
|
|
|
nsresult>
|
|
|
|
GetResult(JSContext* aCx, T* aDOMObject, JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
if (!aDOMObject) {
|
|
|
|
aResult.setNull();
|
|
|
|
return NS_OK;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
const bool ok = GetOrCreateDOMReflector(aCx, aDOMObject, aResult);
|
|
|
|
if (NS_WARN_IF(!ok)) {
|
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
nsresult GetResult(JSContext* aCx, const JS::Handle<JS::Value>* aValue,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
aResult.set(*aValue);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
nsresult GetResult(JSContext* aCx, const uint64_t* aValue,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
aResult.set(JS::NumberValue(*aValue));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2020-05-14 12:42:13 +03:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
nsresult GetResult(JSContext* aCx, StructuredCloneReadInfoChild&& aCloneInfo,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
const bool ok =
|
|
|
|
IDBObjectStore::DeserializeValue(aCx, std::move(aCloneInfo), aResult);
|
2020-05-14 12:42:13 +03:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
if (NS_WARN_IF(!ok)) {
|
|
|
|
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
2020-05-14 12:42:13 +03:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
nsresult GetResult(JSContext* aCx, StructuredCloneReadInfoChild* aCloneInfo,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
return GetResult(aCx, std::move(*aCloneInfo), aResult);
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
nsresult GetResult(JSContext* aCx,
|
|
|
|
nsTArray<StructuredCloneReadInfoChild>* aCloneInfos,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
|
|
|
|
if (NS_WARN_IF(!array)) {
|
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
if (!aCloneInfos->IsEmpty()) {
|
|
|
|
const uint32_t count = aCloneInfos->Length();
|
|
|
|
|
|
|
|
if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
|
2014-09-27 03:21:57 +04:00
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
for (uint32_t index = 0; index < count; index++) {
|
|
|
|
auto& cloneInfo = aCloneInfos->ElementAt(index);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
JS::Rooted<JS::Value> value(aCx);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
const nsresult rv = GetResult(aCx, std::move(cloneInfo), &value);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
if (NS_WARN_IF(
|
|
|
|
!JS_DefineElement(aCx, array, index, value, JSPROP_ENUMERATE))) {
|
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
2020-05-14 12:42:23 +03:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
aResult.setObject(*array);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult GetResult(JSContext* aCx, const Key* aKey,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
const nsresult rv = aKey->ToJSVal(aCx, aResult);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2020-05-14 12:42:23 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
nsresult GetResult(JSContext* aCx, const nsTArray<Key>* aKeys,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
|
|
|
|
if (NS_WARN_IF(!array)) {
|
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
if (!aKeys->IsEmpty()) {
|
|
|
|
const uint32_t count = aKeys->Length();
|
|
|
|
|
|
|
|
if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
|
2014-09-27 03:21:57 +04:00
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
for (uint32_t index = 0; index < count; index++) {
|
|
|
|
const Key& key = aKeys->ElementAt(index);
|
|
|
|
MOZ_ASSERT(!key.IsUnset());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
JS::Rooted<JS::Value> value(aCx);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
const nsresult rv = GetResult(aCx, &key, &value);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
if (NS_WARN_IF(
|
|
|
|
!JS_DefineElement(aCx, array, index, value, JSPROP_ENUMERATE))) {
|
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-14 12:42:23 +03:00
|
|
|
|
|
|
|
aResult.setObject(*array);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
} // namespace detail
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class PermissionRequestMainProcessHelper final : public PermissionRequestBase {
|
2014-09-27 03:21:57 +04:00
|
|
|
BackgroundFactoryRequestChild* mActor;
|
2020-04-01 12:54:43 +03:00
|
|
|
SafeRefPtr<IDBFactory> mFactory;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
public:
|
|
|
|
PermissionRequestMainProcessHelper(BackgroundFactoryRequestChild* aActor,
|
2020-04-01 12:54:43 +03:00
|
|
|
SafeRefPtr<IDBFactory> aFactory,
|
2015-04-10 19:10:00 +03:00
|
|
|
Element* aOwnerElement,
|
2014-09-27 03:21:57 +04:00
|
|
|
nsIPrincipal* aPrincipal)
|
2015-04-10 19:10:00 +03:00
|
|
|
: PermissionRequestBase(aOwnerElement, aPrincipal),
|
2014-09-27 03:21:57 +04:00
|
|
|
mActor(aActor),
|
2020-04-01 12:54:43 +03:00
|
|
|
mFactory(std::move(aFactory)) {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aActor);
|
2020-04-01 12:54:43 +03:00
|
|
|
MOZ_ASSERT(mFactory);
|
2014-09-27 03:21:57 +04:00
|
|
|
aActor->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2019-10-03 10:56:45 +03:00
|
|
|
~PermissionRequestMainProcessHelper() = default;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
private:
|
2015-03-21 19:28:04 +03:00
|
|
|
virtual void OnPromptComplete(PermissionValue aPermissionValue) override;
|
2014-09-27 03:21:57 +04:00
|
|
|
};
|
|
|
|
|
2019-11-08 16:22:08 +03:00
|
|
|
auto DeserializeStructuredCloneFiles(
|
2016-10-25 22:19:06 +03:00
|
|
|
IDBDatabase* aDatabase,
|
|
|
|
const nsTArray<SerializedStructuredCloneFile>& aSerializedFiles,
|
2019-11-08 16:22:08 +03:00
|
|
|
bool aForPreprocess) {
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT_IF(aForPreprocess, aSerializedFiles.Length() == 1);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
return TransformIntoNewArray(
|
|
|
|
aSerializedFiles,
|
|
|
|
[aForPreprocess, &database = *aDatabase](
|
|
|
|
const auto& serializedFile) -> StructuredCloneFileChild {
|
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
aForPreprocess,
|
|
|
|
serializedFile.type() == StructuredCloneFileBase::eStructuredClone);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
const BlobOrMutableFile& blobOrMutableFile = serializedFile.file();
|
2019-07-03 13:23:33 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
switch (serializedFile.type()) {
|
|
|
|
case StructuredCloneFileBase::eBlob: {
|
|
|
|
MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::TIPCBlob);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
const IPCBlob& ipcBlob = blobOrMutableFile.get_IPCBlob();
|
2014-10-08 20:15:22 +04:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
const RefPtr<BlobImpl> blobImpl =
|
|
|
|
IPCBlobUtils::Deserialize(ipcBlob);
|
|
|
|
MOZ_ASSERT(blobImpl);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
RefPtr<Blob> blob =
|
|
|
|
Blob::Create(database.GetOwnerGlobal(), blobImpl);
|
|
|
|
MOZ_ASSERT(blob);
|
2015-09-09 14:15:05 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
return {StructuredCloneFileBase::eBlob, std::move(blob)};
|
2019-11-08 16:22:08 +03:00
|
|
|
}
|
2015-09-09 14:15:05 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
case StructuredCloneFileBase::eMutableFile: {
|
|
|
|
MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t ||
|
|
|
|
blobOrMutableFile.type() ==
|
|
|
|
BlobOrMutableFile::TPBackgroundMutableFileChild);
|
2015-09-09 14:15:05 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
switch (blobOrMutableFile.type()) {
|
|
|
|
case BlobOrMutableFile::Tnull_t:
|
|
|
|
return StructuredCloneFileChild{
|
|
|
|
StructuredCloneFileBase::eMutableFile};
|
2015-09-09 14:15:05 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
case BlobOrMutableFile::TPBackgroundMutableFileChild: {
|
|
|
|
auto* const actor = static_cast<BackgroundMutableFileChild*>(
|
|
|
|
blobOrMutableFile.get_PBackgroundMutableFileChild());
|
|
|
|
MOZ_ASSERT(actor);
|
2015-09-09 14:15:05 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
actor->EnsureDOMObject();
|
2015-09-09 14:15:05 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
auto* const mutableFile =
|
|
|
|
static_cast<IDBMutableFile*>(actor->GetDOMObject());
|
|
|
|
MOZ_ASSERT(mutableFile);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
auto file = StructuredCloneFileChild{mutableFile};
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
actor->ReleaseDOMObject();
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
return file;
|
|
|
|
}
|
2016-12-09 04:37:13 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
default:
|
|
|
|
MOZ_CRASH("Should never get here!");
|
|
|
|
}
|
|
|
|
}
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
case StructuredCloneFileBase::eStructuredClone: {
|
|
|
|
if (aForPreprocess) {
|
|
|
|
MOZ_ASSERT(blobOrMutableFile.type() ==
|
|
|
|
BlobOrMutableFile::TIPCBlob);
|
2016-10-25 22:18:58 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
const IPCBlob& ipcBlob = blobOrMutableFile.get_IPCBlob();
|
2019-07-03 13:23:33 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
const RefPtr<BlobImpl> blobImpl =
|
|
|
|
IPCBlobUtils::Deserialize(ipcBlob);
|
|
|
|
MOZ_ASSERT(blobImpl);
|
2018-08-08 20:13:16 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
RefPtr<Blob> blob =
|
|
|
|
Blob::Create(database.GetOwnerGlobal(), blobImpl);
|
|
|
|
MOZ_ASSERT(blob);
|
2019-07-03 13:23:33 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
return {StructuredCloneFileBase::eStructuredClone,
|
|
|
|
std::move(blob)};
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t);
|
2018-08-08 20:13:16 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
return StructuredCloneFileChild{
|
|
|
|
StructuredCloneFileBase::eStructuredClone};
|
|
|
|
}
|
2019-11-08 16:22:08 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
case StructuredCloneFileBase::eWasmBytecode:
|
|
|
|
case StructuredCloneFileBase::eWasmCompiled: {
|
|
|
|
MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t);
|
2018-08-08 20:13:16 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
return StructuredCloneFileChild{serializedFile.type()};
|
2019-11-08 16:22:08 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
// Don't set mBlob, support for storing WebAssembly.Modules has been
|
|
|
|
// removed in bug 1469395. Support for de-serialization of
|
|
|
|
// WebAssembly.Modules has been removed in bug 1561876. Full removal
|
|
|
|
// is tracked in bug 1487479.
|
|
|
|
}
|
2019-11-08 16:22:08 +03:00
|
|
|
|
2020-04-21 17:35:03 +03:00
|
|
|
default:
|
|
|
|
MOZ_CRASH("Should never get here!");
|
|
|
|
}
|
|
|
|
});
|
2019-11-08 16:22:08 +03:00
|
|
|
}
|
|
|
|
|
2020-03-11 20:20:05 +03:00
|
|
|
JSStructuredCloneData PreprocessingNotSupported() {
|
|
|
|
MOZ_CRASH("Preprocessing not (yet) supported!");
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename PreprocessInfoAccessor>
|
2020-03-11 20:30:33 +03:00
|
|
|
StructuredCloneReadInfoChild DeserializeStructuredCloneReadInfo(
|
2020-03-11 20:20:05 +03:00
|
|
|
SerializedStructuredCloneReadInfo&& aSerialized,
|
|
|
|
IDBDatabase* const aDatabase,
|
|
|
|
PreprocessInfoAccessor preprocessInfoAccessor) {
|
|
|
|
// XXX Make this a class invariant of SerializedStructuredCloneReadInfo.
|
|
|
|
MOZ_ASSERT_IF(aSerialized.hasPreprocessInfo(),
|
|
|
|
0 == aSerialized.data().data.Size());
|
2020-03-11 20:30:33 +03:00
|
|
|
return {aSerialized.hasPreprocessInfo() ? preprocessInfoAccessor()
|
|
|
|
: std::move(aSerialized.data().data),
|
|
|
|
DeserializeStructuredCloneFiles(aDatabase, aSerialized.files(),
|
|
|
|
/* aForPreprocess */ false),
|
|
|
|
aDatabase};
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2019-12-04 15:59:09 +03:00
|
|
|
// TODO: Remove duplication between DispatchErrorEvent and DispatchSucessEvent.
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
void DispatchErrorEvent(
|
2020-07-01 23:14:23 +03:00
|
|
|
MovingNotNull<RefPtr<IDBRequest>> aRequest, nsresult aErrorCode,
|
2020-04-21 17:32:51 +03:00
|
|
|
const SafeRefPtr<IDBTransaction>& aTransaction = nullptr,
|
|
|
|
RefPtr<Event> aEvent = nullptr) {
|
2020-07-01 23:14:23 +03:00
|
|
|
const RefPtr<IDBRequest> request = std::move(aRequest);
|
|
|
|
|
|
|
|
request->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(NS_FAILED(aErrorCode));
|
|
|
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
|
|
|
|
2018-05-19 00:55:18 +03:00
|
|
|
AUTO_PROFILER_LABEL("IndexedDB:DispatchErrorEvent", DOM);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
request->SetError(aErrorCode);
|
|
|
|
|
|
|
|
if (!aEvent) {
|
|
|
|
// Make an error event and fire it at the target.
|
2020-04-21 17:32:51 +03:00
|
|
|
aEvent = CreateGenericEvent(request, nsDependentString(kErrorEventType),
|
|
|
|
eDoesBubble, eCancelable);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2020-04-21 17:32:51 +03:00
|
|
|
MOZ_ASSERT(aEvent);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
// XXX This is redundant if we are called from
|
2020-05-14 12:42:23 +03:00
|
|
|
// DispatchSuccessEvent.
|
2014-09-27 03:21:57 +04:00
|
|
|
Maybe<AutoSetCurrentTransaction> asct;
|
|
|
|
if (aTransaction) {
|
2020-04-21 17:32:51 +03:00
|
|
|
asct.emplace(SomeRef(*aTransaction));
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
if (aTransaction && aTransaction->IsInactive()) {
|
|
|
|
aTransaction->TransitionToActive();
|
2019-12-04 15:59:09 +03:00
|
|
|
}
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
if (aTransaction) {
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2020-07-03 12:39:24 +03:00
|
|
|
"Firing %s event with error 0x%x", "%s (0x%" PRIx32 ")",
|
2020-04-21 17:32:51 +03:00
|
|
|
aTransaction->LoggingSerialNumber(), request->LoggingSerialNumber(),
|
2020-07-03 12:39:24 +03:00
|
|
|
IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
|
|
|
|
static_cast<uint32_t>(aErrorCode));
|
2014-10-16 08:56:52 +04:00
|
|
|
} else {
|
2020-07-03 12:39:24 +03:00
|
|
|
IDB_LOG_MARK_CHILD_REQUEST("Firing %s event with error 0x%x",
|
|
|
|
"%s (0x%" PRIx32 ")",
|
2019-09-27 13:11:45 +03:00
|
|
|
request->LoggingSerialNumber(),
|
|
|
|
IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
|
2020-07-03 12:39:24 +03:00
|
|
|
static_cast<uint32_t>(aErrorCode));
|
2014-10-16 08:56:52 +04:00
|
|
|
}
|
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
IgnoredErrorResult rv;
|
2019-10-03 10:56:45 +03:00
|
|
|
const bool doDefault =
|
|
|
|
request->DispatchEvent(*aEvent, CallerType::System, rv);
|
2018-04-05 20:42:41 +03:00
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
2014-09-27 03:21:57 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
MOZ_ASSERT(!aTransaction || aTransaction->IsActive() ||
|
|
|
|
aTransaction->IsAborted() ||
|
|
|
|
aTransaction->WasExplicitlyCommitted());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
if (aTransaction && aTransaction->IsActive()) {
|
|
|
|
aTransaction->TransitionToInactive();
|
2019-12-04 15:59:09 +03:00
|
|
|
|
|
|
|
// Do not abort the transaction here if this request is failed due to the
|
|
|
|
// abortion of its transaction to ensure that the correct error cause of
|
|
|
|
// the abort event be set in IDBTransaction::FireCompleteOrAbortEvents()
|
|
|
|
// later.
|
|
|
|
if (aErrorCode != NS_ERROR_DOM_INDEXEDDB_ABORT_ERR) {
|
|
|
|
WidgetEvent* const internalEvent = aEvent->WidgetEventPtr();
|
|
|
|
MOZ_ASSERT(internalEvent);
|
|
|
|
|
|
|
|
if (internalEvent->mFlags.mExceptionWasRaised) {
|
2020-04-21 17:32:51 +03:00
|
|
|
aTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
2019-12-04 15:59:09 +03:00
|
|
|
} else if (doDefault) {
|
2020-04-21 17:32:51 +03:00
|
|
|
aTransaction->Abort(request);
|
2019-12-04 15:59:09 +03:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
template <typename T>
|
|
|
|
void SetResultAndDispatchSuccessEvent(
|
2020-07-01 23:14:23 +03:00
|
|
|
const NotNull<RefPtr<IDBRequest>>& aRequest,
|
|
|
|
const SafeRefPtr<IDBTransaction>& aTransaction, T& aPtr,
|
2020-05-14 12:42:23 +03:00
|
|
|
RefPtr<Event> aEvent) {
|
2020-12-08 20:49:30 +03:00
|
|
|
const auto autoTransaction =
|
|
|
|
AutoSetCurrentTransaction{aTransaction.maybeDeref()};
|
2014-11-20 06:03:01 +03:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
AUTO_PROFILER_LABEL("IndexedDB:SetResultAndDispatchSuccessEvent", DOM);
|
|
|
|
|
|
|
|
aRequest->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (aTransaction && aTransaction->IsAborted()) {
|
|
|
|
DispatchErrorEvent(aRequest, aTransaction->AbortCode(), aTransaction);
|
2014-11-20 06:03:01 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!aEvent) {
|
2020-07-01 23:14:23 +03:00
|
|
|
aEvent =
|
|
|
|
CreateGenericEvent(aRequest.get(), nsDependentString(kSuccessEventType),
|
|
|
|
eDoesNotBubble, eNotCancelable);
|
2014-11-20 06:03:01 +03:00
|
|
|
}
|
|
|
|
MOZ_ASSERT(aEvent);
|
2019-12-04 15:59:09 +03:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
aRequest->SetResult(
|
2020-07-01 23:14:23 +03:00
|
|
|
[&aPtr](JSContext* aCx, JS::MutableHandle<JS::Value> aResult) {
|
2020-05-14 12:42:23 +03:00
|
|
|
MOZ_ASSERT(aCx);
|
2020-07-01 23:14:23 +03:00
|
|
|
return detail::GetResult(aCx, &aPtr, aResult);
|
2020-05-14 12:42:23 +03:00
|
|
|
});
|
2020-04-21 17:32:51 +03:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
detail::DispatchSuccessEvent(aRequest, aTransaction, aEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace detail {
|
2020-07-01 23:14:23 +03:00
|
|
|
void DispatchSuccessEvent(const NotNull<RefPtr<IDBRequest>>& aRequest,
|
2020-05-14 12:42:23 +03:00
|
|
|
const SafeRefPtr<IDBTransaction>& aTransaction,
|
|
|
|
const RefPtr<Event>& aEvent) {
|
|
|
|
if (aTransaction && aTransaction->IsInactive()) {
|
|
|
|
aTransaction->TransitionToActive();
|
2019-12-04 15:59:09 +03:00
|
|
|
}
|
2014-11-20 06:03:01 +03:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
if (aTransaction) {
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2020-05-14 12:42:23 +03:00
|
|
|
"Firing %s event", "%s", aTransaction->LoggingSerialNumber(),
|
|
|
|
aRequest->LoggingSerialNumber(),
|
2014-10-16 08:56:52 +04:00
|
|
|
IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
|
|
|
|
} else {
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_REQUEST("Firing %s event", "%s",
|
2020-05-14 12:42:23 +03:00
|
|
|
aRequest->LoggingSerialNumber(),
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
|
2014-10-16 08:56:52 +04:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
MOZ_ASSERT_IF(aTransaction && !aTransaction->WasExplicitlyCommitted(),
|
|
|
|
aTransaction->IsActive() && !aTransaction->IsAborted());
|
2017-11-17 06:01:27 +03:00
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
IgnoredErrorResult rv;
|
2020-05-14 12:42:23 +03:00
|
|
|
aRequest->DispatchEvent(*aEvent, rv);
|
2018-04-05 20:42:41 +03:00
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
2014-11-20 06:03:01 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-03 10:56:45 +03:00
|
|
|
WidgetEvent* const internalEvent = aEvent->WidgetEventPtr();
|
2014-11-20 06:03:01 +03:00
|
|
|
MOZ_ASSERT(internalEvent);
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
if (aTransaction && aTransaction->IsActive()) {
|
|
|
|
aTransaction->TransitionToInactive();
|
2019-12-04 15:59:09 +03:00
|
|
|
|
2017-11-17 06:01:27 +03:00
|
|
|
if (internalEvent->mFlags.mExceptionWasRaised) {
|
2020-05-14 12:42:23 +03:00
|
|
|
aTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
2017-11-17 06:01:27 +03:00
|
|
|
} else {
|
|
|
|
// To handle upgrade transaction.
|
2020-05-14 12:42:23 +03:00
|
|
|
aTransaction->CommitIfNotStarted();
|
2017-11-17 06:01:27 +03:00
|
|
|
}
|
2014-11-20 06:03:01 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-14 12:42:23 +03:00
|
|
|
} // namespace detail
|
2014-11-20 06:03:01 +03:00
|
|
|
|
2016-10-25 22:19:06 +03:00
|
|
|
PRFileDesc* GetFileDescriptorFromStream(nsIInputStream* aStream) {
|
|
|
|
MOZ_ASSERT(aStream);
|
|
|
|
|
2019-10-03 10:56:45 +03:00
|
|
|
const nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(aStream);
|
2016-10-25 22:19:06 +03:00
|
|
|
if (NS_WARN_IF(!fileMetadata)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRFileDesc* fileDesc;
|
2019-10-03 10:56:45 +03:00
|
|
|
const nsresult rv = fileMetadata->GetFileDescriptor(&fileDesc);
|
2016-10-25 22:19:06 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(fileDesc);
|
|
|
|
|
|
|
|
return fileDesc;
|
|
|
|
}
|
|
|
|
|
2015-05-06 11:07:57 +03:00
|
|
|
class WorkerPermissionChallenge;
|
|
|
|
|
|
|
|
// This class calles WorkerPermissionChallenge::OperationCompleted() in the
|
|
|
|
// worker thread.
|
2015-09-08 11:11:36 +03:00
|
|
|
class WorkerPermissionOperationCompleted final : public WorkerControlRunnable {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<WorkerPermissionChallenge> mChallenge;
|
2015-05-06 11:07:57 +03:00
|
|
|
|
|
|
|
public:
|
|
|
|
WorkerPermissionOperationCompleted(WorkerPrivate* aWorkerPrivate,
|
|
|
|
WorkerPermissionChallenge* aChallenge)
|
2015-09-08 11:11:36 +03:00
|
|
|
: WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
|
2015-05-06 11:07:57 +03:00
|
|
|
mChallenge(aChallenge) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool WorkerRun(JSContext* aCx,
|
|
|
|
WorkerPrivate* aWorkerPrivate) override;
|
|
|
|
};
|
|
|
|
|
|
|
|
// This class used to do prompting in the main thread and main process.
|
|
|
|
class WorkerPermissionRequest final : public PermissionRequestBase {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<WorkerPermissionChallenge> mChallenge;
|
2015-05-06 11:07:57 +03:00
|
|
|
|
|
|
|
public:
|
|
|
|
WorkerPermissionRequest(Element* aElement, nsIPrincipal* aPrincipal,
|
|
|
|
WorkerPermissionChallenge* aChallenge)
|
|
|
|
: PermissionRequestBase(aElement, aPrincipal), mChallenge(aChallenge) {
|
2015-07-04 04:29:00 +03:00
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
2015-05-06 11:07:57 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(aChallenge);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
~WorkerPermissionRequest() { MOZ_ASSERT(NS_IsMainThread()); }
|
|
|
|
|
|
|
|
virtual void OnPromptComplete(PermissionValue aPermissionValue) override;
|
|
|
|
};
|
|
|
|
|
2016-04-26 03:23:21 +03:00
|
|
|
class WorkerPermissionChallenge final : public Runnable {
|
2015-05-06 11:07:57 +03:00
|
|
|
public:
|
|
|
|
WorkerPermissionChallenge(WorkerPrivate* aWorkerPrivate,
|
|
|
|
BackgroundFactoryRequestChild* aActor,
|
2020-04-01 12:54:43 +03:00
|
|
|
SafeRefPtr<IDBFactory> aFactory,
|
2020-02-18 19:37:49 +03:00
|
|
|
PrincipalInfo&& aPrincipalInfo)
|
2017-01-13 11:40:58 +03:00
|
|
|
: Runnable("indexedDB::WorkerPermissionChallenge"),
|
|
|
|
mWorkerPrivate(aWorkerPrivate),
|
2015-05-06 11:07:57 +03:00
|
|
|
mActor(aActor),
|
2020-04-01 12:54:43 +03:00
|
|
|
mFactory(std::move(aFactory)),
|
2020-02-18 19:37:49 +03:00
|
|
|
mPrincipalInfo(std::move(aPrincipalInfo)) {
|
2015-05-06 11:07:57 +03:00
|
|
|
MOZ_ASSERT(mWorkerPrivate);
|
|
|
|
MOZ_ASSERT(aActor);
|
2020-04-01 12:54:43 +03:00
|
|
|
MOZ_ASSERT(mFactory);
|
2015-05-06 11:07:57 +03:00
|
|
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
|
}
|
|
|
|
|
2016-07-04 09:19:10 +03:00
|
|
|
bool Dispatch() {
|
|
|
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
|
if (NS_WARN_IF(!mWorkerPrivate->ModifyBusyCountFromWorker(true))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-13 11:40:58 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(mWorkerPrivate->DispatchToMainThread(this)))) {
|
2016-07-04 09:19:10 +03:00
|
|
|
mWorkerPrivate->ModifyBusyCountFromWorker(false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-06 11:07:57 +03:00
|
|
|
NS_IMETHOD
|
|
|
|
Run() override {
|
2019-10-03 10:56:45 +03:00
|
|
|
const bool completed = RunInternal();
|
2015-05-06 11:07:57 +03:00
|
|
|
if (completed) {
|
|
|
|
OperationCompleted();
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OperationCompleted() {
|
|
|
|
if (NS_IsMainThread()) {
|
2019-10-03 10:56:45 +03:00
|
|
|
const RefPtr<WorkerPermissionOperationCompleted> runnable =
|
2015-05-06 11:07:57 +03:00
|
|
|
new WorkerPermissionOperationCompleted(mWorkerPrivate, this);
|
|
|
|
|
2016-02-26 23:23:12 +03:00
|
|
|
MOZ_ALWAYS_TRUE(runnable->Dispatch());
|
2015-05-06 11:07:57 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
2020-04-01 12:54:43 +03:00
|
|
|
const SafeRefPtr<IDBFactory> factory = std::move(mFactory);
|
2020-01-09 17:43:57 +03:00
|
|
|
Unused << factory; // XXX see Bug 1605075
|
2015-05-06 11:07:57 +03:00
|
|
|
|
|
|
|
mActor->SendPermissionRetry();
|
|
|
|
mActor = nullptr;
|
|
|
|
|
|
|
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
2016-07-04 09:19:10 +03:00
|
|
|
mWorkerPrivate->ModifyBusyCountFromWorker(false);
|
2015-05-06 11:07:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool RunInternal() {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
// Walk up to our containing page
|
|
|
|
WorkerPrivate* wp = mWorkerPrivate;
|
|
|
|
while (wp->GetParent()) {
|
|
|
|
wp = wp->GetParent();
|
|
|
|
}
|
|
|
|
|
2019-10-03 10:56:45 +03:00
|
|
|
nsPIDOMWindowInner* const window = wp->GetWindow();
|
2015-05-06 11:07:57 +03:00
|
|
|
if (!window) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-05-03 22:44:38 +03:00
|
|
|
QM_TRY_UNWRAP(auto principal,
|
|
|
|
mozilla::ipc::PrincipalInfoToPrincipal(mPrincipalInfo), true);
|
2020-05-12 22:02:05 +03:00
|
|
|
|
2015-07-04 04:29:00 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
2019-10-03 10:56:45 +03:00
|
|
|
const nsCOMPtr<Element> ownerElement =
|
2015-05-06 11:07:57 +03:00
|
|
|
do_QueryInterface(window->GetChromeEventHandler());
|
|
|
|
if (NS_WARN_IF(!ownerElement)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<WorkerPermissionRequest> helper =
|
2015-05-06 11:07:57 +03:00
|
|
|
new WorkerPermissionRequest(ownerElement, principal, this);
|
|
|
|
|
2021-05-03 22:44:38 +03:00
|
|
|
QM_TRY_INSPECT(const PermissionRequestBase::PermissionValue& permission,
|
|
|
|
helper->PromptIfNeeded(), true);
|
2015-05-06 11:07:57 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(permission == PermissionRequestBase::kPermissionAllowed ||
|
|
|
|
permission == PermissionRequestBase::kPermissionDenied ||
|
|
|
|
permission == PermissionRequestBase::kPermissionPrompt);
|
|
|
|
|
|
|
|
return permission != PermissionRequestBase::kPermissionPrompt;
|
|
|
|
}
|
|
|
|
|
2019-04-10 01:39:01 +03:00
|
|
|
BrowserChild* browserChild = BrowserChild::GetFrom(window);
|
|
|
|
MOZ_ASSERT(browserChild);
|
2015-05-06 11:07:57 +03:00
|
|
|
|
2019-03-22 22:14:01 +03:00
|
|
|
RefPtr<WorkerPermissionChallenge> self(this);
|
2020-02-10 23:52:56 +03:00
|
|
|
browserChild->SendIndexedDBPermissionRequest(principal)->Then(
|
2020-06-23 08:05:36 +03:00
|
|
|
GetCurrentSerialEventTarget(), __func__,
|
2020-02-10 23:52:56 +03:00
|
|
|
[self](const uint32_t& aPermission) { self->OperationCompleted(); },
|
|
|
|
[](const mozilla::ipc::ResponseRejectReason) {});
|
2015-05-06 11:07:57 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-10-03 10:56:45 +03:00
|
|
|
WorkerPrivate* const mWorkerPrivate;
|
2015-05-06 11:07:57 +03:00
|
|
|
BackgroundFactoryRequestChild* mActor;
|
2020-04-01 12:54:43 +03:00
|
|
|
SafeRefPtr<IDBFactory> mFactory;
|
2019-10-03 10:56:45 +03:00
|
|
|
const PrincipalInfo mPrincipalInfo;
|
2015-05-06 11:07:57 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
void WorkerPermissionRequest::OnPromptComplete(
|
|
|
|
PermissionValue aPermissionValue) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
mChallenge->OperationCompleted();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WorkerPermissionOperationCompleted::WorkerRun(
|
|
|
|
JSContext* aCx, WorkerPrivate* aWorkerPrivate) {
|
|
|
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
|
|
|
mChallenge->OperationCompleted();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-06-07 13:36:42 +03:00
|
|
|
class MOZ_STACK_CLASS AutoSetCurrentFileHandle final {
|
2021-08-16 20:05:41 +03:00
|
|
|
using BackgroundChildImpl = mozilla::ipc::BackgroundChildImpl;
|
2017-06-07 13:36:42 +03:00
|
|
|
|
|
|
|
IDBFileHandle* const mFileHandle;
|
|
|
|
IDBFileHandle* mPreviousFileHandle;
|
|
|
|
IDBFileHandle** mThreadLocalSlot;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit AutoSetCurrentFileHandle(IDBFileHandle* aFileHandle)
|
|
|
|
: mFileHandle(aFileHandle),
|
|
|
|
mPreviousFileHandle(nullptr),
|
|
|
|
mThreadLocalSlot(nullptr) {
|
|
|
|
if (aFileHandle) {
|
|
|
|
BackgroundChildImpl::ThreadLocal* threadLocal =
|
|
|
|
BackgroundChildImpl::GetThreadLocalForCurrentThread();
|
|
|
|
MOZ_ASSERT(threadLocal);
|
|
|
|
|
|
|
|
// Hang onto this location for resetting later.
|
|
|
|
mThreadLocalSlot = &threadLocal->mCurrentFileHandle;
|
|
|
|
|
|
|
|
// Save the current value.
|
|
|
|
mPreviousFileHandle = *mThreadLocalSlot;
|
|
|
|
|
|
|
|
// Set the new value.
|
|
|
|
*mThreadLocalSlot = aFileHandle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~AutoSetCurrentFileHandle() {
|
|
|
|
MOZ_ASSERT_IF(mThreadLocalSlot, mFileHandle);
|
|
|
|
MOZ_ASSERT_IF(mThreadLocalSlot, *mThreadLocalSlot == mFileHandle);
|
|
|
|
|
|
|
|
if (mThreadLocalSlot) {
|
|
|
|
// Reset old value.
|
|
|
|
*mThreadLocalSlot = mPreviousFileHandle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IDBFileHandle* FileHandle() const { return mFileHandle; }
|
|
|
|
};
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
template <typename T>
|
|
|
|
void SetFileHandleResultAndDispatchSuccessEvent(
|
|
|
|
const RefPtr<IDBFileRequest>& aFileRequest,
|
|
|
|
const RefPtr<IDBFileHandle>& aFileHandle, T* aPtr);
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
namespace detail {
|
|
|
|
nsresult GetFileHandleResult(const RefPtr<IDBFileRequest>& aFileRequest,
|
|
|
|
JSContext* aCx, const nsCString* aString,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
const nsCString& data = *aString;
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
nsresult rv;
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
if (!aFileRequest->HasEncoding()) {
|
|
|
|
JS::Rooted<JSObject*> arrayBuffer(aCx);
|
|
|
|
rv = nsContentUtils::CreateArrayBuffer(aCx, data, arrayBuffer.address());
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2017-06-07 13:36:42 +03:00
|
|
|
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
aResult.setObject(*arrayBuffer);
|
2017-06-07 13:36:42 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
// Try the API argument.
|
|
|
|
const Encoding* encoding = Encoding::ForLabel(aFileRequest->GetEncoding());
|
|
|
|
if (!encoding) {
|
|
|
|
// API argument failed. Since we are dealing with a file system file,
|
|
|
|
// we don't have a meaningful type attribute for the blob available,
|
|
|
|
// so proceeding to the next step, which is defaulting to UTF-8.
|
|
|
|
encoding = UTF_8_ENCODING;
|
|
|
|
}
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
nsString tmpString;
|
2021-11-08 11:14:00 +03:00
|
|
|
std::tie(rv, std::ignore) = encoding->Decode(data, tmpString);
|
2020-05-14 12:42:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
|
|
|
}
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
if (NS_WARN_IF(!xpc::StringToJsval(aCx, tmpString, aResult))) {
|
|
|
|
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
|
|
|
}
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
nsresult GetFileHandleResult(const RefPtr<IDBFileRequest>& /*aFileRequest*/,
|
|
|
|
JSContext* aCx,
|
|
|
|
const FileRequestMetadata* aMetadata,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
|
|
|
|
if (NS_WARN_IF(!obj)) {
|
|
|
|
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
|
|
|
}
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
const Maybe<uint64_t>& size = aMetadata->size();
|
|
|
|
if (size.isSome()) {
|
|
|
|
JS::Rooted<JS::Value> number(aCx, JS_NumberValue(size.value()));
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "size", number, 0))) {
|
2017-06-07 13:36:42 +03:00
|
|
|
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
const Maybe<int64_t>& lastModified = aMetadata->lastModified();
|
|
|
|
if (lastModified.isSome()) {
|
|
|
|
JS::Rooted<JSObject*> date(
|
|
|
|
aCx, JS::NewDateObject(aCx, JS::TimeClip(lastModified.value())));
|
|
|
|
if (NS_WARN_IF(!date)) {
|
2017-06-07 13:36:42 +03:00
|
|
|
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "lastModified", date, 0))) {
|
|
|
|
return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
|
2017-06-07 13:36:42 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-14 12:42:16 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
aResult.setObject(*obj);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult GetFileHandleResult(const RefPtr<IDBFileRequest>& /*aFileRequest*/,
|
|
|
|
JSContext* aCx,
|
|
|
|
const JS::Handle<JS::Value>* aValue,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
aResult.set(*aValue);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
} // namespace detail
|
2017-06-07 13:36:42 +03:00
|
|
|
|
|
|
|
void DispatchFileHandleErrorEvent(IDBFileRequest* aFileRequest,
|
|
|
|
nsresult aErrorCode,
|
|
|
|
IDBFileHandle* aFileHandle) {
|
|
|
|
MOZ_ASSERT(aFileRequest);
|
|
|
|
aFileRequest->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(NS_FAILED(aErrorCode));
|
|
|
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_FILEHANDLE);
|
|
|
|
MOZ_ASSERT(aFileHandle);
|
|
|
|
|
2019-10-03 10:56:45 +03:00
|
|
|
const RefPtr<IDBFileRequest> fileRequest = aFileRequest;
|
|
|
|
const RefPtr<IDBFileHandle> fileHandle = aFileHandle;
|
2017-06-07 13:36:42 +03:00
|
|
|
|
|
|
|
AutoSetCurrentFileHandle ascfh(aFileHandle);
|
|
|
|
|
|
|
|
fileRequest->FireError(aErrorCode);
|
|
|
|
|
|
|
|
MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
template <typename T>
|
|
|
|
void SetFileHandleResultAndDispatchSuccessEvent(
|
|
|
|
const RefPtr<IDBFileRequest>& aFileRequest,
|
|
|
|
const RefPtr<IDBFileHandle>& aFileHandle, T* aPtr) {
|
|
|
|
MOZ_ASSERT(aFileRequest);
|
|
|
|
MOZ_ASSERT(aFileHandle);
|
|
|
|
MOZ_ASSERT(aPtr);
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
auto autoFileHandle = AutoSetCurrentFileHandle{aFileHandle};
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
aFileRequest->AssertIsOnOwningThread();
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
if (aFileHandle->IsAborted()) {
|
|
|
|
aFileRequest->FireError(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
|
2017-06-07 13:36:42 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
MOZ_ASSERT(aFileHandle->IsOpen());
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
aFileRequest->SetResult(
|
|
|
|
[aFileRequest, aPtr](JSContext* aCx,
|
|
|
|
JS::MutableHandle<JS::Value> aResult) {
|
|
|
|
return detail::GetFileHandleResult(aFileRequest, aCx, aPtr, aResult);
|
|
|
|
});
|
2017-06-07 13:36:42 +03:00
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
MOZ_ASSERT(aFileHandle->IsOpen() || aFileHandle->IsAborted());
|
2017-06-07 13:36:42 +03:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
auto GetKeyOperator(const IDBCursorDirection aDirection) {
|
2019-11-05 17:40:37 +03:00
|
|
|
switch (aDirection) {
|
2020-01-10 18:23:52 +03:00
|
|
|
case IDBCursorDirection::Next:
|
|
|
|
case IDBCursorDirection::Nextunique:
|
2019-11-05 17:40:37 +03:00
|
|
|
return &Key::operator>=;
|
2020-01-10 18:23:52 +03:00
|
|
|
case IDBCursorDirection::Prev:
|
|
|
|
case IDBCursorDirection::Prevunique:
|
2019-11-05 17:40:37 +03:00
|
|
|
return &Key::operator<=;
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Should never get here.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
// Does not need to be threadsafe since this only runs on one thread, but
|
|
|
|
// inheriting from CancelableRunnable is easy.
|
|
|
|
template <typename T>
|
|
|
|
class DelayedActionRunnable final : public CancelableRunnable {
|
|
|
|
using ActionFunc = void (T::*)();
|
|
|
|
|
2020-08-28 18:50:38 +03:00
|
|
|
SafeRefPtr<T> mActor;
|
2020-01-10 18:23:52 +03:00
|
|
|
RefPtr<IDBRequest> mRequest;
|
|
|
|
ActionFunc mActionFunc;
|
|
|
|
|
|
|
|
public:
|
2020-08-28 18:50:38 +03:00
|
|
|
explicit DelayedActionRunnable(SafeRefPtr<T> aActor, ActionFunc aActionFunc)
|
2020-01-10 18:23:52 +03:00
|
|
|
: CancelableRunnable("indexedDB::DelayedActionRunnable"),
|
2020-08-28 18:50:38 +03:00
|
|
|
mActor(std::move(aActor)),
|
|
|
|
mRequest(mActor->GetRequest()),
|
2020-01-10 18:23:52 +03:00
|
|
|
mActionFunc(aActionFunc) {
|
2020-08-28 18:50:38 +03:00
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
2020-01-10 18:23:52 +03:00
|
|
|
MOZ_ASSERT(mRequest);
|
|
|
|
MOZ_ASSERT(mActionFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
~DelayedActionRunnable() = default;
|
|
|
|
|
|
|
|
NS_DECL_NSIRUNNABLE
|
|
|
|
nsresult Cancel() override;
|
|
|
|
};
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2016-10-25 22:19:06 +03:00
|
|
|
/*******************************************************************************
|
|
|
|
* Actor class declarations
|
|
|
|
******************************************************************************/
|
|
|
|
|
2020-12-03 12:04:44 +03:00
|
|
|
// DiscardableRunnable is used to make workers happy.
|
2016-10-25 22:19:06 +03:00
|
|
|
class BackgroundRequestChild::PreprocessHelper final
|
2020-12-03 12:04:44 +03:00
|
|
|
: public DiscardableRunnable,
|
2017-05-23 08:52:47 +03:00
|
|
|
public nsIInputStreamCallback,
|
2017-09-08 17:06:26 +03:00
|
|
|
public nsIFileMetadataCallback {
|
2019-07-03 13:23:33 +03:00
|
|
|
enum class State {
|
|
|
|
// Just created on the owning thread, dispatched to the thread pool. Next
|
|
|
|
// step is either Finishing if stream was ready to be read or
|
|
|
|
// WaitingForStreamReady if the stream is not ready.
|
|
|
|
Initial,
|
|
|
|
|
|
|
|
// Waiting for stream to be ready on a thread pool thread. Next state is
|
|
|
|
// Finishing.
|
|
|
|
WaitingForStreamReady,
|
2017-05-23 08:52:47 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
// Waiting to finish/finishing on the owning thread. Next step is Completed.
|
|
|
|
Finishing,
|
2017-05-23 08:52:47 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
// All done.
|
|
|
|
Completed
|
|
|
|
};
|
|
|
|
|
2019-10-03 10:56:45 +03:00
|
|
|
const nsCOMPtr<nsIEventTarget> mOwningEventTarget;
|
2017-05-23 08:52:47 +03:00
|
|
|
RefPtr<TaskQueue> mTaskQueue;
|
2019-07-03 13:23:33 +03:00
|
|
|
nsCOMPtr<nsIInputStream> mStream;
|
|
|
|
UniquePtr<JSStructuredCloneData> mCloneData;
|
|
|
|
BackgroundRequestChild* mActor;
|
2019-10-03 10:56:45 +03:00
|
|
|
const uint32_t mCloneDataIndex;
|
2016-10-25 22:19:06 +03:00
|
|
|
nsresult mResultCode;
|
2019-07-03 13:23:33 +03:00
|
|
|
State mState;
|
2016-10-25 22:19:06 +03:00
|
|
|
|
|
|
|
public:
|
2019-07-03 13:23:33 +03:00
|
|
|
PreprocessHelper(uint32_t aCloneDataIndex, BackgroundRequestChild* aActor)
|
2020-12-03 12:04:44 +03:00
|
|
|
: DiscardableRunnable(
|
2017-01-13 11:40:58 +03:00
|
|
|
"indexedDB::BackgroundRequestChild::PreprocessHelper"),
|
2017-06-01 23:42:05 +03:00
|
|
|
mOwningEventTarget(aActor->GetActorEventTarget()),
|
2016-10-25 22:19:06 +03:00
|
|
|
mActor(aActor),
|
2019-07-03 13:23:33 +03:00
|
|
|
mCloneDataIndex(aCloneDataIndex),
|
|
|
|
mResultCode(NS_OK),
|
|
|
|
mState(State::Initial) {
|
2016-10-25 22:19:06 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
aActor->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsOnOwningThread() const {
|
2017-06-01 23:42:05 +03:00
|
|
|
MOZ_ASSERT(mOwningEventTarget);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
|
|
|
bool current;
|
2017-06-01 23:42:05 +03:00
|
|
|
return NS_SUCCEEDED(mOwningEventTarget->IsOnCurrentThread(¤t)) &&
|
|
|
|
current;
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void AssertIsOnOwningThread() const { MOZ_ASSERT(IsOnOwningThread()); }
|
|
|
|
|
|
|
|
void ClearActor() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mActor = nullptr;
|
|
|
|
}
|
|
|
|
|
2020-03-19 14:35:03 +03:00
|
|
|
nsresult Init(const StructuredCloneFileChild& aFile);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
|
|
|
nsresult Dispatch();
|
|
|
|
|
|
|
|
private:
|
|
|
|
~PreprocessHelper() {
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(mState == State::Initial || mState == State::Completed);
|
|
|
|
|
2017-05-23 08:52:47 +03:00
|
|
|
if (mTaskQueue) {
|
|
|
|
mTaskQueue->BeginShutdown();
|
|
|
|
}
|
|
|
|
}
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsresult Start();
|
2017-05-23 08:52:47 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsresult ProcessStream();
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
void Finish();
|
2017-09-08 17:06:26 +03:00
|
|
|
|
2017-05-23 08:52:47 +03:00
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
2016-10-25 22:19:06 +03:00
|
|
|
NS_DECL_NSIRUNNABLE
|
2017-05-23 08:52:47 +03:00
|
|
|
NS_DECL_NSIINPUTSTREAMCALLBACK
|
2017-09-08 17:06:26 +03:00
|
|
|
NS_DECL_NSIFILEMETADATACALLBACK
|
2016-10-25 22:19:06 +03:00
|
|
|
};
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
/*******************************************************************************
|
|
|
|
* Local class implementations
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
void PermissionRequestMainProcessHelper::OnPromptComplete(
|
|
|
|
PermissionValue aPermissionValue) {
|
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
mActor->SendPermissionRetry();
|
|
|
|
|
|
|
|
mActor = nullptr;
|
|
|
|
mFactory = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundRequestChildBase
|
|
|
|
******************************************************************************/
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
BackgroundRequestChildBase::BackgroundRequestChildBase(
|
|
|
|
MovingNotNull<RefPtr<IDBRequest>> aRequest)
|
|
|
|
: mRequest(std::move(aRequest)) {
|
|
|
|
mRequest->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChildBase);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundRequestChildBase::~BackgroundRequestChildBase() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChildBase);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundRequestChildBase::AssertIsOnOwningThread() const {
|
|
|
|
mRequest->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundFactoryChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
2020-04-01 12:54:43 +03:00
|
|
|
BackgroundFactoryChild::BackgroundFactoryChild(IDBFactory& aFactory)
|
|
|
|
: mFactory(&aFactory) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2020-04-01 12:54:43 +03:00
|
|
|
mFactory->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundFactoryChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundFactoryChild::~BackgroundFactoryChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundFactoryChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFactoryChild::SendDeleteMeInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mFactory) {
|
|
|
|
mFactory->ClearBackgroundActor();
|
|
|
|
mFactory = nullptr;
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundIDBFactoryChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFactoryChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (mFactory) {
|
|
|
|
mFactory->ClearBackgroundActor();
|
|
|
|
#ifdef DEBUG
|
|
|
|
mFactory = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundIDBFactoryRequestChild*
|
|
|
|
BackgroundFactoryChild::AllocPBackgroundIDBFactoryRequestChild(
|
|
|
|
const FactoryRequestParams& aParams) {
|
|
|
|
MOZ_CRASH(
|
|
|
|
"PBackgroundIDBFactoryRequestChild actors should be manually "
|
|
|
|
"constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundFactoryChild::DeallocPBackgroundIDBFactoryRequestChild(
|
|
|
|
PBackgroundIDBFactoryRequestChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundFactoryRequestChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundIDBDatabaseChild*
|
|
|
|
BackgroundFactoryChild::AllocPBackgroundIDBDatabaseChild(
|
|
|
|
const DatabaseSpec& aSpec, PBackgroundIDBFactoryRequestChild* aRequest) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2019-10-03 10:56:45 +03:00
|
|
|
auto* const request = static_cast<BackgroundFactoryRequestChild*>(aRequest);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(request);
|
|
|
|
|
|
|
|
return new BackgroundDatabaseChild(aSpec, request);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundFactoryChild::DeallocPBackgroundIDBDatabaseChild(
|
|
|
|
PBackgroundIDBDatabaseChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundDatabaseChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-02-10 10:13:45 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
BackgroundFactoryChild::RecvPBackgroundIDBDatabaseConstructor(
|
|
|
|
PBackgroundIDBDatabaseChild* aActor, const DatabaseSpec& aSpec,
|
|
|
|
PBackgroundIDBFactoryRequestChild* aRequest) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundFactoryRequestChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundFactoryRequestChild::BackgroundFactoryRequestChild(
|
2020-07-01 23:14:23 +03:00
|
|
|
SafeRefPtr<IDBFactory> aFactory,
|
|
|
|
MovingNotNull<RefPtr<IDBOpenDBRequest>> aOpenRequest, bool aIsDeleteOp,
|
|
|
|
uint64_t aRequestedVersion)
|
|
|
|
: BackgroundRequestChildBase(std::move(aOpenRequest)),
|
2020-04-01 12:54:43 +03:00
|
|
|
mFactory(std::move(aFactory)),
|
2017-10-30 09:13:40 +03:00
|
|
|
mDatabaseActor(nullptr),
|
2014-09-27 03:21:57 +04:00
|
|
|
mRequestedVersion(aRequestedVersion),
|
|
|
|
mIsDeleteOp(aIsDeleteOp) {
|
|
|
|
// Can't assert owning thread here because IPDL has not yet set our manager!
|
2020-04-01 12:54:43 +03:00
|
|
|
MOZ_ASSERT(mFactory);
|
|
|
|
mFactory->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundFactoryRequestChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundFactoryRequestChild::~BackgroundFactoryRequestChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundFactoryRequestChild);
|
|
|
|
}
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
NotNull<IDBOpenDBRequest*> BackgroundFactoryRequestChild::GetOpenDBRequest()
|
|
|
|
const {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
// XXX NotNull might provide something to encapsulate this
|
|
|
|
return WrapNotNullUnchecked(
|
|
|
|
static_cast<IDBOpenDBRequest*>(mRequest.get().get()));
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2017-10-30 09:13:40 +03:00
|
|
|
void BackgroundFactoryRequestChild::SetDatabaseActor(
|
|
|
|
BackgroundDatabaseChild* aActor) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!aActor || !mDatabaseActor);
|
|
|
|
|
|
|
|
mDatabaseActor = aActor;
|
|
|
|
}
|
|
|
|
|
2022-03-03 11:33:15 +03:00
|
|
|
void BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(NS_FAILED(aResponse));
|
|
|
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
|
|
|
|
|
|
|
mRequest->Reset();
|
|
|
|
|
|
|
|
DispatchErrorEvent(mRequest, aResponse);
|
|
|
|
|
2017-10-30 09:13:40 +03:00
|
|
|
if (mDatabaseActor) {
|
|
|
|
mDatabaseActor->ReleaseDOMObject();
|
|
|
|
MOZ_ASSERT(!mDatabaseActor);
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2022-03-03 11:33:15 +03:00
|
|
|
void BackgroundFactoryRequestChild::HandleResponse(
|
2014-09-27 03:21:57 +04:00
|
|
|
const OpenDatabaseRequestResponse& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mRequest->Reset();
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
auto* databaseActor =
|
2014-09-27 03:21:57 +04:00
|
|
|
static_cast<BackgroundDatabaseChild*>(aResponse.databaseChild());
|
|
|
|
MOZ_ASSERT(databaseActor);
|
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
IDBDatabase* const database = [this, databaseActor]() -> IDBDatabase* {
|
2020-07-01 23:14:23 +03:00
|
|
|
IDBDatabase* database = databaseActor->GetDOMObject();
|
|
|
|
if (!database) {
|
|
|
|
Unused << this;
|
2015-06-20 19:08:30 +03:00
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
if (NS_WARN_IF(!databaseActor->EnsureDOMObject())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2020-07-01 23:14:23 +03:00
|
|
|
MOZ_ASSERT(mDatabaseActor);
|
2015-06-20 19:08:30 +03:00
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
database = databaseActor->GetDOMObject();
|
|
|
|
MOZ_ASSERT(database);
|
|
|
|
|
|
|
|
MOZ_ASSERT(!database->IsClosed());
|
|
|
|
}
|
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
return database;
|
2020-07-01 23:14:23 +03:00
|
|
|
}();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
if (!database || database->IsClosed()) {
|
2015-06-20 19:08:30 +03:00
|
|
|
// If the database was closed already, which is only possible if we fired an
|
|
|
|
// "upgradeneeded" event, then we shouldn't fire a "success" event here.
|
|
|
|
// Instead we fire an error event with AbortErr.
|
|
|
|
DispatchErrorEvent(mRequest, NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
|
|
|
} else {
|
2020-07-01 23:14:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, nullptr, *database);
|
2015-06-20 19:08:30 +03:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
if (database) {
|
|
|
|
MOZ_ASSERT(mDatabaseActor == databaseActor);
|
|
|
|
|
|
|
|
databaseActor->ReleaseDOMObject();
|
|
|
|
} else {
|
|
|
|
databaseActor->SendDeleteMeInternal();
|
|
|
|
}
|
2017-10-30 09:13:40 +03:00
|
|
|
MOZ_ASSERT(!mDatabaseActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2022-03-03 11:33:15 +03:00
|
|
|
void BackgroundFactoryRequestChild::HandleResponse(
|
2014-09-27 03:21:57 +04:00
|
|
|
const DeleteDatabaseRequestResponse& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
RefPtr<Event> successEvent = IDBVersionChangeEvent::Create(
|
2020-07-01 23:14:23 +03:00
|
|
|
mRequest.get(), nsDependentString(kSuccessEventType),
|
2014-09-27 03:21:57 +04:00
|
|
|
aResponse.previousVersion());
|
2014-12-17 09:26:15 +03:00
|
|
|
MOZ_ASSERT(successEvent);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, nullptr, JS::UndefinedHandleValue,
|
2020-05-14 12:42:23 +03:00
|
|
|
std::move(successEvent));
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2017-10-30 09:13:40 +03:00
|
|
|
MOZ_ASSERT(!mDatabaseActor);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFactoryRequestChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
2014-12-17 09:26:15 +03:00
|
|
|
if (aWhy != Deletion) {
|
2020-07-01 23:14:23 +03:00
|
|
|
GetOpenDBRequest()->NoteComplete();
|
2014-12-17 09:26:15 +03:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundFactoryRequestChild::Recv__delete__(
|
|
|
|
const FactoryRequestResponse& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
switch (aResponse.type()) {
|
|
|
|
case FactoryRequestResponse::Tnsresult:
|
2022-03-03 11:33:15 +03:00
|
|
|
HandleResponse(aResponse.get_nsresult());
|
2014-12-17 09:26:15 +03:00
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
case FactoryRequestResponse::TOpenDatabaseRequestResponse:
|
2022-03-03 11:33:15 +03:00
|
|
|
HandleResponse(aResponse.get_OpenDatabaseRequestResponse());
|
2014-12-17 09:26:15 +03:00
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
case FactoryRequestResponse::TDeleteDatabaseRequestResponse:
|
2022-03-03 11:33:15 +03:00
|
|
|
HandleResponse(aResponse.get_DeleteDatabaseRequestResponse());
|
2014-12-17 09:26:15 +03:00
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
default:
|
2022-03-03 11:33:15 +03:00
|
|
|
return IPC_FAIL(this, "Unknown response type!");
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
auto request = GetOpenDBRequest();
|
2014-12-17 09:26:15 +03:00
|
|
|
request->NoteComplete();
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundFactoryRequestChild::RecvPermissionChallenge(
|
2020-02-18 19:37:49 +03:00
|
|
|
PrincipalInfo&& aPrincipalInfo) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (!NS_IsMainThread()) {
|
2015-05-06 11:07:57 +03:00
|
|
|
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
|
|
|
MOZ_ASSERT(workerPrivate);
|
|
|
|
workerPrivate->AssertIsOnWorkerThread();
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<WorkerPermissionChallenge> challenge = new WorkerPermissionChallenge(
|
2020-04-01 12:54:43 +03:00
|
|
|
workerPrivate, this, mFactory.clonePtr(), std::move(aPrincipalInfo));
|
2016-11-15 06:26:00 +03:00
|
|
|
if (!challenge->Dispatch()) {
|
2022-03-11 18:41:58 +03:00
|
|
|
QM_WARNONLY_TRY(OkIf(SendPermissionRetry()));
|
2016-11-15 06:26:00 +03:00
|
|
|
}
|
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2021-05-03 22:44:38 +03:00
|
|
|
QM_TRY_UNWRAP(auto principal,
|
|
|
|
mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo),
|
2022-03-11 18:41:58 +03:00
|
|
|
IPC_FAIL(this, "PrincipalInfoToPrincipal failed!"));
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-07-04 04:29:00 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
2019-03-29 21:05:11 +03:00
|
|
|
nsCOMPtr<nsIGlobalObject> global = mFactory->GetParentObject();
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(window);
|
|
|
|
|
2015-04-10 19:10:00 +03:00
|
|
|
nsCOMPtr<Element> ownerElement =
|
|
|
|
do_QueryInterface(window->GetChromeEventHandler());
|
|
|
|
if (NS_WARN_IF(!ownerElement)) {
|
2015-09-08 11:11:36 +03:00
|
|
|
// If this fails, the page was navigated. Fail the permission check by
|
|
|
|
// forcing an immediate retry.
|
2022-03-11 18:41:58 +03:00
|
|
|
QM_WARNONLY_TRY(OkIf(SendPermissionRetry()));
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2015-04-10 19:10:00 +03:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<PermissionRequestMainProcessHelper> helper =
|
2020-04-01 12:54:43 +03:00
|
|
|
new PermissionRequestMainProcessHelper(this, mFactory.clonePtr(),
|
|
|
|
ownerElement, principal);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2021-05-03 22:44:38 +03:00
|
|
|
QM_TRY_INSPECT(const PermissionRequestBase::PermissionValue& permission,
|
2022-03-11 18:41:58 +03:00
|
|
|
helper->PromptIfNeeded(),
|
|
|
|
IPC_FAIL(this, "PromptIfNeeded failed!"));
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MOZ_ASSERT(permission == PermissionRequestBase::kPermissionAllowed ||
|
|
|
|
permission == PermissionRequestBase::kPermissionDenied ||
|
|
|
|
permission == PermissionRequestBase::kPermissionPrompt);
|
|
|
|
|
|
|
|
if (permission != PermissionRequestBase::kPermissionPrompt) {
|
|
|
|
SendPermissionRetry();
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2019-04-10 01:39:01 +03:00
|
|
|
RefPtr<BrowserChild> browserChild = mFactory->GetBrowserChild();
|
|
|
|
MOZ_ASSERT(browserChild);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-02-10 23:52:56 +03:00
|
|
|
browserChild->SendIndexedDBPermissionRequest(principal)->Then(
|
2020-06-23 08:05:36 +03:00
|
|
|
GetCurrentSerialEventTarget(), __func__,
|
2020-02-10 23:52:56 +03:00
|
|
|
[this](const uint32_t& aPermission) {
|
|
|
|
this->AssertIsOnOwningThread();
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
this->SendPermissionRetry();
|
|
|
|
},
|
|
|
|
[](const mozilla::ipc::ResponseRejectReason) {});
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundFactoryRequestChild::RecvBlocked(
|
2020-02-27 15:17:47 +03:00
|
|
|
const uint64_t aCurrentVersion) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
const nsDependentString type(kBlockedEventType);
|
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
RefPtr<Event> blockedEvent;
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mIsDeleteOp) {
|
|
|
|
blockedEvent =
|
2020-07-01 23:14:23 +03:00
|
|
|
IDBVersionChangeEvent::Create(mRequest.get(), type, aCurrentVersion);
|
2014-12-17 09:26:15 +03:00
|
|
|
MOZ_ASSERT(blockedEvent);
|
2014-09-27 03:21:57 +04:00
|
|
|
} else {
|
|
|
|
blockedEvent = IDBVersionChangeEvent::Create(
|
2020-07-01 23:14:23 +03:00
|
|
|
mRequest.get(), type, aCurrentVersion, mRequestedVersion);
|
2014-12-17 09:26:15 +03:00
|
|
|
MOZ_ASSERT(blockedEvent);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBRequest> kungFuDeathGrip = mRequest;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_REQUEST("Firing \"blocked\" event", "\"blocked\"",
|
|
|
|
kungFuDeathGrip->LoggingSerialNumber());
|
2014-10-16 08:56:52 +04:00
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
IgnoredErrorResult rv;
|
|
|
|
kungFuDeathGrip->DispatchEvent(*blockedEvent, rv);
|
|
|
|
if (rv.Failed()) {
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_WARNING("Failed to dispatch event!");
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundDatabaseChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundDatabaseChild::BackgroundDatabaseChild(
|
|
|
|
const DatabaseSpec& aSpec, BackgroundFactoryRequestChild* aOpenRequestActor)
|
2019-12-19 12:57:49 +03:00
|
|
|
: mSpec(MakeUnique<DatabaseSpec>(aSpec)),
|
2014-09-27 03:21:57 +04:00
|
|
|
mOpenRequestActor(aOpenRequestActor),
|
|
|
|
mDatabase(nullptr) {
|
|
|
|
// Can't assert owning thread here because IPDL has not yet set our manager!
|
|
|
|
MOZ_ASSERT(aOpenRequestActor);
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundDatabaseChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundDatabaseChild::~BackgroundDatabaseChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundDatabaseChild);
|
|
|
|
}
|
|
|
|
|
2017-06-07 08:55:00 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundDatabaseChild::AssertIsOnOwningThread() const {
|
|
|
|
static_cast<BackgroundFactoryChild*>(Manager())->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void BackgroundDatabaseChild::SendDeleteMeInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!mTemporaryStrongDatabase);
|
|
|
|
MOZ_ASSERT(!mOpenRequestActor);
|
|
|
|
|
|
|
|
if (mDatabase) {
|
|
|
|
mDatabase->ClearBackgroundActor();
|
|
|
|
mDatabase = nullptr;
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundIDBDatabaseChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
bool BackgroundDatabaseChild::EnsureDOMObject() {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mOpenRequestActor);
|
|
|
|
|
|
|
|
if (mTemporaryStrongDatabase) {
|
|
|
|
MOZ_ASSERT(!mSpec);
|
2020-07-01 23:14:23 +03:00
|
|
|
MOZ_ASSERT(mDatabase == mTemporaryStrongDatabase);
|
2020-10-08 13:27:53 +03:00
|
|
|
return true;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mSpec);
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
const auto request = mOpenRequestActor->GetOpenDBRequest();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-01 12:54:43 +03:00
|
|
|
auto& factory =
|
2014-09-27 03:21:57 +04:00
|
|
|
static_cast<BackgroundFactoryChild*>(Manager())->GetDOMObject();
|
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
if (!factory.GetParentObject()) {
|
|
|
|
// Already disconnected from global.
|
|
|
|
|
|
|
|
// We need to clear mOpenRequestActor here, since that would otherwise be
|
|
|
|
// done by ReleaseDOMObject, which cannot be called if EnsureDOMObject
|
|
|
|
// failed.
|
|
|
|
mOpenRequestActor = nullptr;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-04-01 12:54:43 +03:00
|
|
|
// TODO: This AcquireStrongRefFromRawPtr looks suspicious. This should be
|
|
|
|
// changed or at least well explained, see also comment on
|
|
|
|
// BackgroundFactoryChild.
|
|
|
|
mTemporaryStrongDatabase = IDBDatabase::Create(
|
|
|
|
request, SafeRefPtr{&factory, AcquireStrongRefFromRawPtr{}}, this,
|
|
|
|
std::move(mSpec));
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MOZ_ASSERT(mTemporaryStrongDatabase);
|
|
|
|
mTemporaryStrongDatabase->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mDatabase = mTemporaryStrongDatabase;
|
2017-10-30 09:13:40 +03:00
|
|
|
|
|
|
|
mOpenRequestActor->SetDatabaseActor(this);
|
2020-10-08 13:27:53 +03:00
|
|
|
|
|
|
|
return true;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundDatabaseChild::ReleaseDOMObject() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTemporaryStrongDatabase);
|
|
|
|
mTemporaryStrongDatabase->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mOpenRequestActor);
|
|
|
|
MOZ_ASSERT(mDatabase == mTemporaryStrongDatabase);
|
|
|
|
|
2017-10-30 09:13:40 +03:00
|
|
|
mOpenRequestActor->SetDatabaseActor(nullptr);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mOpenRequestActor = nullptr;
|
|
|
|
|
|
|
|
// This may be the final reference to the IDBDatabase object so we may end up
|
|
|
|
// calling SendDeleteMeInternal() here. Make sure everything is cleaned up
|
|
|
|
// properly before proceeding.
|
|
|
|
mTemporaryStrongDatabase = nullptr;
|
2020-07-01 23:14:23 +03:00
|
|
|
|
|
|
|
// XXX Why isn't mDatabase set to nullptr here?
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundDatabaseChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (mDatabase) {
|
|
|
|
mDatabase->ClearBackgroundActor();
|
|
|
|
#ifdef DEBUG
|
|
|
|
mDatabase = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundIDBDatabaseFileChild*
|
|
|
|
BackgroundDatabaseChild::AllocPBackgroundIDBDatabaseFileChild(
|
2017-05-23 08:50:33 +03:00
|
|
|
const IPCBlob& aIPCBlob) {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_CRASH("PBackgroundIDBFileChild actors should be manually constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundDatabaseChild::DeallocPBackgroundIDBDatabaseFileChild(
|
|
|
|
PBackgroundIDBDatabaseFileChild* aActor) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete aActor;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
PBackgroundIDBDatabaseRequestChild*
|
|
|
|
BackgroundDatabaseChild::AllocPBackgroundIDBDatabaseRequestChild(
|
|
|
|
const DatabaseRequestParams& aParams) {
|
|
|
|
MOZ_CRASH(
|
|
|
|
"PBackgroundIDBDatabaseRequestChild actors should be manually "
|
|
|
|
"constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundDatabaseChild::DeallocPBackgroundIDBDatabaseRequestChild(
|
|
|
|
PBackgroundIDBDatabaseRequestChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundDatabaseRequestChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-05-06 15:20:32 +03:00
|
|
|
already_AddRefed<PBackgroundIDBVersionChangeTransactionChild>
|
2014-09-27 03:21:57 +04:00
|
|
|
BackgroundDatabaseChild::AllocPBackgroundIDBVersionChangeTransactionChild(
|
2020-02-27 15:17:47 +03:00
|
|
|
const uint64_t aCurrentVersion, const uint64_t aRequestedVersion,
|
|
|
|
const int64_t aNextObjectStoreId, const int64_t aNextIndexId) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
return RefPtr{new BackgroundVersionChangeTransactionChild(
|
|
|
|
mOpenRequestActor->GetOpenDBRequest())}
|
|
|
|
.forget();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2014-09-27 03:21:57 +04:00
|
|
|
BackgroundDatabaseChild::RecvPBackgroundIDBVersionChangeTransactionConstructor(
|
|
|
|
PBackgroundIDBVersionChangeTransactionChild* aActor,
|
|
|
|
const uint64_t& aCurrentVersion, const uint64_t& aRequestedVersion,
|
|
|
|
const int64_t& aNextObjectStoreId, const int64_t& aNextIndexId) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
MOZ_ASSERT(mOpenRequestActor);
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
auto* const actor =
|
|
|
|
static_cast<BackgroundVersionChangeTransactionChild*>(aActor);
|
|
|
|
|
|
|
|
if (!EnsureDOMObject()) {
|
|
|
|
NS_WARNING("Factory is already disconnected from global");
|
|
|
|
|
|
|
|
actor->SendDeleteMeInternal(true);
|
|
|
|
|
|
|
|
// XXX This is a hack to ensure that transaction/request serial numbers stay
|
|
|
|
// in sync between parent and child. Actually, it might be better to create
|
|
|
|
// an IDBTransaction in the child and abort that.
|
|
|
|
Unused
|
|
|
|
<< mozilla::ipc::BackgroundChildImpl::GetThreadLocalForCurrentThread()
|
|
|
|
->mIndexedDBThreadLocal->NextTransactionSN(
|
|
|
|
IDBTransaction::Mode::VersionChange);
|
|
|
|
Unused << IDBRequest::NextSerialNumber();
|
|
|
|
|
|
|
|
// If we return IPC_FAIL_NO_REASON(this) here, we crash...
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-10-08 13:27:53 +03:00
|
|
|
MOZ_ASSERT(!mDatabase->IsInvalidated());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
// XXX NotNull might encapsulate this
|
|
|
|
const auto request =
|
|
|
|
WrapNotNullUnchecked(RefPtr{mOpenRequestActor->GetOpenDBRequest().get()});
|
2014-11-14 05:20:38 +03:00
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
SafeRefPtr<IDBTransaction> transaction = IDBTransaction::CreateVersionChange(
|
2014-11-14 05:20:38 +03:00
|
|
|
mDatabase, actor, request, aNextObjectStoreId, aNextIndexId);
|
2017-06-16 14:06:36 +03:00
|
|
|
MOZ_ASSERT(transaction);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
transaction->AssertIsOnOwningThread();
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
actor->SetDOMTransaction(transaction.clonePtr());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
const auto database = WrapNotNull(mDatabase);
|
|
|
|
|
|
|
|
database->EnterSetVersionTransaction(aRequestedVersion);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
request->SetTransaction(transaction.clonePtr());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2018-04-20 19:53:17 +03:00
|
|
|
RefPtr<Event> upgradeNeededEvent = IDBVersionChangeEvent::Create(
|
2020-07-01 23:14:23 +03:00
|
|
|
request.get(), nsDependentString(kUpgradeNeededEventType),
|
|
|
|
aCurrentVersion, aRequestedVersion);
|
2014-12-17 09:26:15 +03:00
|
|
|
MOZ_ASSERT(upgradeNeededEvent);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(
|
|
|
|
WrapNotNullUnchecked<RefPtr<IDBRequest>>(request.get()), transaction,
|
|
|
|
*database, std::move(upgradeNeededEvent));
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
PBackgroundMutableFileChild*
|
|
|
|
BackgroundDatabaseChild::AllocPBackgroundMutableFileChild(
|
|
|
|
const nsString& aName, const nsString& aType) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2017-06-07 13:36:42 +03:00
|
|
|
return new BackgroundMutableFileChild(aName, aType);
|
2015-09-09 14:15:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundDatabaseChild::DeallocPBackgroundMutableFileChild(
|
|
|
|
PBackgroundMutableFileChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundMutableFileChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mozilla::ipc::IPCResult BackgroundDatabaseChild::RecvVersionChange(
|
2020-02-27 15:17:47 +03:00
|
|
|
const uint64_t aOldVersion, const Maybe<uint64_t> aNewVersion) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (!mDatabase || mDatabase->IsClosed()) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBDatabase> kungFuDeathGrip = mDatabase;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
// Handle bfcache'd windows.
|
2016-08-24 21:12:09 +03:00
|
|
|
if (nsPIDOMWindowInner* owner = kungFuDeathGrip->GetOwner()) {
|
2014-09-27 03:21:57 +04:00
|
|
|
// The database must be closed if the window is already frozen.
|
|
|
|
bool shouldAbortAndClose = owner->IsFrozen();
|
|
|
|
|
|
|
|
// Anything in the bfcache has to be evicted and then we have to close the
|
|
|
|
// database also.
|
2020-08-31 21:51:56 +03:00
|
|
|
if (owner->RemoveFromBFCacheSync()) {
|
|
|
|
shouldAbortAndClose = true;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (shouldAbortAndClose) {
|
|
|
|
// Invalidate() doesn't close the database in the parent, so we have
|
|
|
|
// to call Close() and AbortTransactions() manually.
|
2016-08-24 21:12:09 +03:00
|
|
|
kungFuDeathGrip->AbortTransactions(/* aShouldWarn */ false);
|
|
|
|
kungFuDeathGrip->Close();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise fire a versionchange event.
|
|
|
|
const nsDependentString type(kVersionChangeEventType);
|
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
RefPtr<Event> versionChangeEvent;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2019-03-15 20:10:29 +03:00
|
|
|
if (aNewVersion.isNothing()) {
|
|
|
|
versionChangeEvent =
|
|
|
|
IDBVersionChangeEvent::Create(kungFuDeathGrip, type, aOldVersion);
|
|
|
|
MOZ_ASSERT(versionChangeEvent);
|
|
|
|
} else {
|
|
|
|
versionChangeEvent = IDBVersionChangeEvent::Create(
|
|
|
|
kungFuDeathGrip, type, aOldVersion, aNewVersion.value());
|
|
|
|
MOZ_ASSERT(versionChangeEvent);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK("Child : Firing \"versionchange\" event",
|
|
|
|
"C: IDBDatabase \"versionchange\" event", IDB_LOG_ID_STRING());
|
2014-10-16 08:56:52 +04:00
|
|
|
|
2018-04-05 20:42:41 +03:00
|
|
|
IgnoredErrorResult rv;
|
|
|
|
kungFuDeathGrip->DispatchEvent(*versionChangeEvent, rv);
|
|
|
|
if (rv.Failed()) {
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_WARNING("Failed to dispatch event!");
|
|
|
|
}
|
|
|
|
|
2016-08-24 21:12:09 +03:00
|
|
|
if (!kungFuDeathGrip->IsClosed()) {
|
2014-09-27 03:21:57 +04:00
|
|
|
SendBlocked();
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundDatabaseChild::RecvInvalidate() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (mDatabase) {
|
|
|
|
mDatabase->Invalidate();
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2016-05-31 13:08:20 +03:00
|
|
|
BackgroundDatabaseChild::RecvCloseAfterInvalidationComplete() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (mDatabase) {
|
|
|
|
mDatabase->DispatchTrustedEvent(nsDependentString(kCloseEventType));
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-05-31 13:08:20 +03:00
|
|
|
}
|
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundDatabaseRequestChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundDatabaseRequestChild::BackgroundDatabaseRequestChild(
|
2020-07-01 23:14:23 +03:00
|
|
|
IDBDatabase* aDatabase, MovingNotNull<RefPtr<IDBRequest>> aRequest)
|
|
|
|
: BackgroundRequestChildBase(std::move(aRequest)), mDatabase(aDatabase) {
|
2015-09-09 14:15:05 +03:00
|
|
|
// Can't assert owning thread here because IPDL has not yet set our manager!
|
|
|
|
MOZ_ASSERT(aDatabase);
|
|
|
|
aDatabase->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundDatabaseRequestChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundDatabaseRequestChild::~BackgroundDatabaseRequestChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundDatabaseRequestChild);
|
|
|
|
}
|
|
|
|
|
2022-03-03 11:33:15 +03:00
|
|
|
void BackgroundDatabaseRequestChild::HandleResponse(nsresult aResponse) {
|
2015-09-09 14:15:05 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(NS_FAILED(aResponse));
|
|
|
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
|
|
|
|
|
|
|
mRequest->Reset();
|
|
|
|
|
|
|
|
DispatchErrorEvent(mRequest, aResponse);
|
|
|
|
}
|
|
|
|
|
2022-03-03 11:33:15 +03:00
|
|
|
void BackgroundDatabaseRequestChild::HandleResponse(
|
2015-09-09 14:15:05 +03:00
|
|
|
const CreateFileRequestResponse& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mRequest->Reset();
|
|
|
|
|
|
|
|
auto mutableFileActor =
|
|
|
|
static_cast<BackgroundMutableFileChild*>(aResponse.mutableFileChild());
|
|
|
|
MOZ_ASSERT(mutableFileActor);
|
|
|
|
|
|
|
|
mutableFileActor->EnsureDOMObject();
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, nullptr,
|
|
|
|
*WrapNotNull(static_cast<IDBMutableFile*>(
|
|
|
|
mutableFileActor->GetDOMObject())));
|
2015-09-09 14:15:05 +03:00
|
|
|
|
|
|
|
mutableFileActor->ReleaseDOMObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundDatabaseRequestChild::Recv__delete__(
|
|
|
|
const DatabaseRequestResponse& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
switch (aResponse.type()) {
|
|
|
|
case DatabaseRequestResponse::Tnsresult:
|
2022-03-03 11:33:15 +03:00
|
|
|
HandleResponse(aResponse.get_nsresult());
|
|
|
|
break;
|
2015-09-09 14:15:05 +03:00
|
|
|
|
|
|
|
case DatabaseRequestResponse::TCreateFileRequestResponse:
|
2022-03-03 11:33:15 +03:00
|
|
|
HandleResponse(aResponse.get_CreateFileRequestResponse());
|
|
|
|
break;
|
2015-09-09 14:15:05 +03:00
|
|
|
|
|
|
|
default:
|
2022-03-03 11:33:15 +03:00
|
|
|
return IPC_FAIL(this, "Unknown response type!");
|
2015-09-09 14:15:05 +03:00
|
|
|
}
|
|
|
|
|
2022-03-03 11:33:15 +03:00
|
|
|
return IPC_OK();
|
2015-09-09 14:15:05 +03:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundTransactionBase
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundTransactionBase::BackgroundTransactionBase(
|
2020-04-21 17:32:51 +03:00
|
|
|
SafeRefPtr<IDBTransaction> aTransaction)
|
|
|
|
: mTemporaryStrongTransaction(std::move(aTransaction)),
|
|
|
|
mTransaction(mTemporaryStrongTransaction.unsafeGetRawPtr()) {
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
mTransaction->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
MOZ_COUNT_CTOR(BackgroundTransactionBase);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundTransactionBase::AssertIsOnOwningThread() const {
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
mTransaction->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
void BackgroundTransactionBase::NoteActorDestroyed() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT_IF(mTemporaryStrongTransaction, mTransaction);
|
|
|
|
|
|
|
|
if (mTransaction) {
|
|
|
|
mTransaction->ClearBackgroundActor();
|
|
|
|
|
|
|
|
// Normally this would be DEBUG-only but NoteActorDestroyed is also called
|
|
|
|
// from SendDeleteMeInternal. In that case we're going to receive an actual
|
|
|
|
// ActorDestroy call later and we don't want to touch a dead object.
|
|
|
|
mTemporaryStrongTransaction = nullptr;
|
|
|
|
mTransaction = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundTransactionBase::SetDOMTransaction(
|
2020-04-21 17:32:51 +03:00
|
|
|
SafeRefPtr<IDBTransaction> aTransaction) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aTransaction);
|
|
|
|
aTransaction->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!mTemporaryStrongTransaction);
|
|
|
|
MOZ_ASSERT(!mTransaction);
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
mTemporaryStrongTransaction = std::move(aTransaction);
|
|
|
|
mTransaction = mTemporaryStrongTransaction.unsafeGetRawPtr();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundTransactionBase::NoteComplete() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT_IF(mTransaction, mTemporaryStrongTransaction);
|
|
|
|
|
|
|
|
mTemporaryStrongTransaction = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundTransactionChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundTransactionChild::BackgroundTransactionChild(
|
2020-04-21 17:32:51 +03:00
|
|
|
SafeRefPtr<IDBTransaction> aTransaction)
|
|
|
|
: BackgroundTransactionBase(std::move(aTransaction)) {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundTransactionChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundTransactionChild::~BackgroundTransactionChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundTransactionChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundTransactionChild::AssertIsOnOwningThread() const {
|
|
|
|
static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
void BackgroundTransactionChild::SendDeleteMeInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mTransaction) {
|
|
|
|
NoteActorDestroyed();
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundIDBTransactionChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundTransactionChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
NoteActorDestroyed();
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundTransactionChild::RecvComplete(
|
2020-02-27 15:17:47 +03:00
|
|
|
const nsresult aResult) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
mTransaction->FireCompleteOrAbortEvents(aResult);
|
|
|
|
|
|
|
|
NoteComplete();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundIDBRequestChild*
|
|
|
|
BackgroundTransactionChild::AllocPBackgroundIDBRequestChild(
|
|
|
|
const RequestParams& aParams) {
|
|
|
|
MOZ_CRASH(
|
|
|
|
"PBackgroundIDBRequestChild actors should be manually "
|
|
|
|
"constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundTransactionChild::DeallocPBackgroundIDBRequestChild(
|
|
|
|
PBackgroundIDBRequestChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundRequestChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundIDBCursorChild*
|
|
|
|
BackgroundTransactionChild::AllocPBackgroundIDBCursorChild(
|
|
|
|
const OpenCursorParams& aParams) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_CRASH("PBackgroundIDBCursorChild actors should be manually constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundTransactionChild::DeallocPBackgroundIDBCursorChild(
|
|
|
|
PBackgroundIDBCursorChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
delete aActor;
|
2014-09-27 03:21:57 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundVersionChangeTransactionChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundVersionChangeTransactionChild::
|
|
|
|
BackgroundVersionChangeTransactionChild(IDBOpenDBRequest* aOpenDBRequest)
|
|
|
|
: mOpenDBRequest(aOpenDBRequest) {
|
|
|
|
MOZ_ASSERT(aOpenDBRequest);
|
|
|
|
aOpenDBRequest->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundVersionChangeTransactionChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundVersionChangeTransactionChild::
|
|
|
|
~BackgroundVersionChangeTransactionChild() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundVersionChangeTransactionChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundVersionChangeTransactionChild::AssertIsOnOwningThread() const {
|
|
|
|
static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2014-12-17 09:26:15 +03:00
|
|
|
void BackgroundVersionChangeTransactionChild::SendDeleteMeInternal(
|
|
|
|
bool aFailedConstructor) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2014-12-17 09:26:15 +03:00
|
|
|
if (mTransaction || aFailedConstructor) {
|
2014-09-27 03:21:57 +04:00
|
|
|
NoteActorDestroyed();
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(
|
|
|
|
PBackgroundIDBVersionChangeTransactionChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundVersionChangeTransactionChild::ActorDestroy(
|
|
|
|
ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
mOpenDBRequest = nullptr;
|
|
|
|
|
|
|
|
NoteActorDestroyed();
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundVersionChangeTransactionChild::RecvComplete(
|
2020-02-27 15:17:47 +03:00
|
|
|
const nsresult aResult) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (!mTransaction) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mOpenDBRequest);
|
|
|
|
|
|
|
|
IDBDatabase* database = mTransaction->Database();
|
|
|
|
MOZ_ASSERT(database);
|
|
|
|
|
|
|
|
database->ExitSetVersionTransaction();
|
|
|
|
|
|
|
|
if (NS_FAILED(aResult)) {
|
|
|
|
database->Close();
|
|
|
|
}
|
|
|
|
|
2019-05-30 05:53:07 +03:00
|
|
|
RefPtr<IDBOpenDBRequest> request = mOpenDBRequest;
|
|
|
|
MOZ_ASSERT(request);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mTransaction->FireCompleteOrAbortEvents(aResult);
|
|
|
|
|
2019-05-30 05:53:07 +03:00
|
|
|
request->SetTransaction(nullptr);
|
|
|
|
request = nullptr;
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mOpenDBRequest = nullptr;
|
|
|
|
|
|
|
|
NoteComplete();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundIDBRequestChild*
|
|
|
|
BackgroundVersionChangeTransactionChild::AllocPBackgroundIDBRequestChild(
|
|
|
|
const RequestParams& aParams) {
|
|
|
|
MOZ_CRASH(
|
|
|
|
"PBackgroundIDBRequestChild actors should be manually "
|
|
|
|
"constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundVersionChangeTransactionChild::DeallocPBackgroundIDBRequestChild(
|
|
|
|
PBackgroundIDBRequestChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundRequestChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundIDBCursorChild*
|
|
|
|
BackgroundVersionChangeTransactionChild::AllocPBackgroundIDBCursorChild(
|
|
|
|
const OpenCursorParams& aParams) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_CRASH("PBackgroundIDBCursorChild actors should be manually constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundVersionChangeTransactionChild::DeallocPBackgroundIDBCursorChild(
|
|
|
|
PBackgroundIDBCursorChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
delete aActor;
|
2014-09-27 03:21:57 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundMutableFileChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
2017-06-07 13:36:42 +03:00
|
|
|
BackgroundMutableFileChild::BackgroundMutableFileChild(const nsAString& aName,
|
|
|
|
const nsAString& aType)
|
|
|
|
: mMutableFile(nullptr), mName(aName), mType(aType) {
|
2015-09-09 14:15:05 +03:00
|
|
|
// Can't assert owning thread here because IPDL has not yet set our manager!
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundMutableFileChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundMutableFileChild::~BackgroundMutableFileChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundMutableFileChild);
|
|
|
|
}
|
|
|
|
|
2017-06-07 13:36:42 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundMutableFileChild::AssertIsOnOwningThread() const {
|
|
|
|
static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
void BackgroundMutableFileChild::EnsureDOMObject() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mTemporaryStrongMutableFile) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
auto database =
|
|
|
|
static_cast<BackgroundDatabaseChild*>(Manager())->GetDOMObject();
|
|
|
|
MOZ_ASSERT(database);
|
|
|
|
|
2017-06-07 13:36:42 +03:00
|
|
|
mTemporaryStrongMutableFile =
|
2015-09-09 14:15:05 +03:00
|
|
|
new IDBMutableFile(database, this, mName, mType);
|
|
|
|
|
2017-06-07 13:36:42 +03:00
|
|
|
MOZ_ASSERT(mTemporaryStrongMutableFile);
|
|
|
|
mTemporaryStrongMutableFile->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mMutableFile = mTemporaryStrongMutableFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundMutableFileChild::ReleaseDOMObject() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTemporaryStrongMutableFile);
|
|
|
|
mTemporaryStrongMutableFile->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mMutableFile == mTemporaryStrongMutableFile);
|
|
|
|
|
|
|
|
mTemporaryStrongMutableFile = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundMutableFileChild::SendDeleteMeInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!mTemporaryStrongMutableFile);
|
|
|
|
|
|
|
|
if (mMutableFile) {
|
|
|
|
mMutableFile->ClearBackgroundActor();
|
|
|
|
mMutableFile = nullptr;
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundMutableFileChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundMutableFileChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mMutableFile) {
|
|
|
|
mMutableFile->ClearBackgroundActor();
|
|
|
|
#ifdef DEBUG
|
|
|
|
mMutableFile = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundFileHandleChild*
|
|
|
|
BackgroundMutableFileChild::AllocPBackgroundFileHandleChild(
|
|
|
|
const FileMode& aMode) {
|
|
|
|
MOZ_CRASH(
|
|
|
|
"PBackgroundFileHandleChild actors should be manually "
|
|
|
|
"constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundMutableFileChild::DeallocPBackgroundFileHandleChild(
|
|
|
|
PBackgroundFileHandleChild* aActor) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundFileHandleChild*>(aActor);
|
|
|
|
return true;
|
2015-09-09 14:15:05 +03:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundRequestChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
BackgroundRequestChild::BackgroundRequestChild(
|
|
|
|
MovingNotNull<RefPtr<IDBRequest>> aRequest)
|
|
|
|
: BackgroundRequestChildBase(std::move(aRequest)),
|
|
|
|
mTransaction(mRequest->AcquireTransaction()),
|
2016-10-26 07:51:33 +03:00
|
|
|
mRunningPreprocessHelpers(0),
|
2019-07-03 13:23:33 +03:00
|
|
|
mCurrentCloneDataIndex(0),
|
2016-10-26 07:51:33 +03:00
|
|
|
mPreprocessResultCode(NS_OK),
|
|
|
|
mGetAll(false) {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
mTransaction->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundRequestChild::~BackgroundRequestChild() {
|
|
|
|
AssertIsOnOwningThread();
|
2015-03-19 00:20:59 +03:00
|
|
|
MOZ_ASSERT(!mTransaction);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChild);
|
|
|
|
}
|
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
void BackgroundRequestChild::MaybeSendContinue() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mRunningPreprocessHelpers > 0);
|
|
|
|
|
|
|
|
if (--mRunningPreprocessHelpers == 0) {
|
|
|
|
PreprocessResponse response;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(mPreprocessResultCode)) {
|
|
|
|
if (mGetAll) {
|
|
|
|
response = ObjectStoreGetAllPreprocessResponse();
|
|
|
|
} else {
|
|
|
|
response = ObjectStoreGetPreprocessResponse();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
response = mPreprocessResultCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(SendContinue(response));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-25 22:19:06 +03:00
|
|
|
void BackgroundRequestChild::OnPreprocessFinished(
|
2019-07-03 13:23:33 +03:00
|
|
|
uint32_t aCloneDataIndex, UniquePtr<JSStructuredCloneData> aCloneData) {
|
2016-10-25 22:19:06 +03:00
|
|
|
AssertIsOnOwningThread();
|
2019-11-21 19:46:08 +03:00
|
|
|
MOZ_ASSERT(aCloneDataIndex < mCloneInfos.Length());
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(aCloneData);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-11-21 19:46:08 +03:00
|
|
|
auto& cloneInfo = mCloneInfos[aCloneDataIndex];
|
|
|
|
MOZ_ASSERT(cloneInfo.mPreprocessHelper);
|
|
|
|
MOZ_ASSERT(!cloneInfo.mCloneData);
|
|
|
|
|
|
|
|
cloneInfo.mCloneData = std::move(aCloneData);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
MaybeSendContinue();
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-11-21 19:46:08 +03:00
|
|
|
cloneInfo.mPreprocessHelper = nullptr;
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
void BackgroundRequestChild::OnPreprocessFailed(uint32_t aCloneDataIndex,
|
2016-10-26 07:51:33 +03:00
|
|
|
nsresult aErrorCode) {
|
2016-10-25 22:19:06 +03:00
|
|
|
AssertIsOnOwningThread();
|
2019-11-21 19:46:08 +03:00
|
|
|
MOZ_ASSERT(aCloneDataIndex < mCloneInfos.Length());
|
2016-10-25 22:19:06 +03:00
|
|
|
MOZ_ASSERT(NS_FAILED(aErrorCode));
|
2019-11-21 19:46:08 +03:00
|
|
|
|
|
|
|
auto& cloneInfo = mCloneInfos[aCloneDataIndex];
|
|
|
|
MOZ_ASSERT(cloneInfo.mPreprocessHelper);
|
|
|
|
MOZ_ASSERT(!cloneInfo.mCloneData);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
if (NS_SUCCEEDED(mPreprocessResultCode)) {
|
|
|
|
mPreprocessResultCode = aErrorCode;
|
|
|
|
}
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
MaybeSendContinue();
|
|
|
|
|
2019-11-21 19:46:08 +03:00
|
|
|
cloneInfo.mPreprocessHelper = nullptr;
|
2016-10-26 07:51:33 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
UniquePtr<JSStructuredCloneData> BackgroundRequestChild::GetNextCloneData() {
|
|
|
|
AssertIsOnOwningThread();
|
2019-11-21 19:46:08 +03:00
|
|
|
MOZ_ASSERT(mCurrentCloneDataIndex < mCloneInfos.Length());
|
|
|
|
MOZ_ASSERT(mCloneInfos[mCurrentCloneDataIndex].mCloneData);
|
2019-07-03 13:23:33 +03:00
|
|
|
|
2019-11-21 19:46:08 +03:00
|
|
|
return std::move(mCloneInfos[mCurrentCloneDataIndex++].mCloneData);
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void BackgroundRequestChild::HandleResponse(nsresult aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(NS_FAILED(aResponse));
|
|
|
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
DispatchErrorEvent(mRequest, aResponse, mTransaction.clonePtr());
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundRequestChild::HandleResponse(const Key& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(), aResponse);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(), aResponse);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundRequestChild::HandleResponse(
|
2020-03-03 16:50:48 +03:00
|
|
|
SerializedStructuredCloneReadInfo&& aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2019-11-08 16:22:08 +03:00
|
|
|
auto cloneReadInfo = DeserializeStructuredCloneReadInfo(
|
2020-03-11 20:20:05 +03:00
|
|
|
std::move(aResponse), mTransaction->Database(),
|
|
|
|
[this] { return std::move(*GetNextCloneData()); });
|
2019-07-03 13:23:33 +03:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(),
|
2020-07-01 23:14:23 +03:00
|
|
|
cloneReadInfo);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundRequestChild::HandleResponse(
|
2020-03-03 16:50:48 +03:00
|
|
|
nsTArray<SerializedStructuredCloneReadInfo>&& aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-03-11 20:30:33 +03:00
|
|
|
nsTArray<StructuredCloneReadInfoChild> cloneReadInfos;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2021-05-03 22:44:38 +03:00
|
|
|
QM_TRY(OkIf(cloneReadInfos.SetCapacity(aResponse.Length(), fallible)),
|
|
|
|
QM_VOID, ([&aResponse, this](const auto) {
|
|
|
|
// Since we are under memory pressure, release aResponse early.
|
|
|
|
aResponse.Clear();
|
2020-10-23 14:02:11 +03:00
|
|
|
|
2021-05-03 22:44:38 +03:00
|
|
|
DispatchErrorEvent(mRequest, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR,
|
|
|
|
AcquireTransaction());
|
2020-10-23 14:02:11 +03:00
|
|
|
|
2021-05-03 22:44:38 +03:00
|
|
|
MOZ_ASSERT(mTransaction->IsAborted());
|
|
|
|
}));
|
2020-10-23 14:02:11 +03:00
|
|
|
|
|
|
|
std::transform(std::make_move_iterator(aResponse.begin()),
|
|
|
|
std::make_move_iterator(aResponse.end()),
|
|
|
|
MakeBackInserter(cloneReadInfos),
|
|
|
|
[database = mTransaction->Database(), this](
|
|
|
|
SerializedStructuredCloneReadInfo&& serializedCloneInfo) {
|
|
|
|
return DeserializeStructuredCloneReadInfo(
|
|
|
|
std::move(serializedCloneInfo), database,
|
|
|
|
[this] { return std::move(*GetNextCloneData()); });
|
|
|
|
});
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(),
|
2020-07-01 23:14:23 +03:00
|
|
|
cloneReadInfos);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(
|
|
|
|
mRequest, AcquireTransaction(),
|
2020-07-01 23:14:23 +03:00
|
|
|
const_cast<const JS::Handle<JS::Value>&>(aResponse));
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:13 +03:00
|
|
|
void BackgroundRequestChild::HandleResponse(const uint64_t aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(), aResponse);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
nsresult BackgroundRequestChild::HandlePreprocess(
|
2019-07-03 13:23:33 +03:00
|
|
|
const PreprocessInfo& aPreprocessInfo) {
|
2019-11-20 16:26:16 +03:00
|
|
|
return HandlePreprocessInternal(
|
|
|
|
AutoTArray<PreprocessInfo, 1>{aPreprocessInfo});
|
|
|
|
}
|
2016-10-26 07:51:33 +03:00
|
|
|
|
2019-11-20 16:26:16 +03:00
|
|
|
nsresult BackgroundRequestChild::HandlePreprocess(
|
|
|
|
const nsTArray<PreprocessInfo>& aPreprocessInfos) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
mGetAll = true;
|
2016-10-26 07:51:33 +03:00
|
|
|
|
2019-11-20 16:26:16 +03:00
|
|
|
return HandlePreprocessInternal(aPreprocessInfos);
|
2016-10-26 07:51:33 +03:00
|
|
|
}
|
|
|
|
|
2019-11-20 16:26:16 +03:00
|
|
|
nsresult BackgroundRequestChild::HandlePreprocessInternal(
|
2019-07-03 13:23:33 +03:00
|
|
|
const nsTArray<PreprocessInfo>& aPreprocessInfos) {
|
2016-10-26 07:51:33 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
IDBDatabase* database = mTransaction->Database();
|
|
|
|
|
2019-11-21 19:46:08 +03:00
|
|
|
const uint32_t count = aPreprocessInfos.Length();
|
2016-10-26 07:51:33 +03:00
|
|
|
|
2019-11-21 19:46:08 +03:00
|
|
|
mCloneInfos.SetLength(count);
|
2016-10-26 07:51:33 +03:00
|
|
|
|
|
|
|
// TODO: Since we use the stream transport service, this can spawn 25 threads
|
|
|
|
// and has the potential to cause some annoying browser hiccups.
|
|
|
|
// Consider using a single thread or a very small threadpool.
|
|
|
|
for (uint32_t index = 0; index < count; index++) {
|
2019-07-03 13:23:33 +03:00
|
|
|
const PreprocessInfo& preprocessInfo = aPreprocessInfos[index];
|
2016-10-26 07:51:33 +03:00
|
|
|
|
2019-11-08 16:22:08 +03:00
|
|
|
const auto files =
|
|
|
|
DeserializeStructuredCloneFiles(database, preprocessInfo.files(),
|
|
|
|
/* aForPreprocess */ true);
|
2019-07-03 13:23:33 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(files.Length() == 1);
|
2016-10-26 07:51:33 +03:00
|
|
|
|
2019-11-21 19:46:08 +03:00
|
|
|
auto& preprocessHelper = mCloneInfos[index].mPreprocessHelper;
|
|
|
|
preprocessHelper = MakeRefPtr<PreprocessHelper>(index, this);
|
2016-10-26 07:51:33 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsresult rv = preprocessHelper->Init(files[0]);
|
2016-10-26 07:51:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = preprocessHelper->Dispatch();
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
mRunningPreprocessHelpers++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void BackgroundRequestChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
2019-11-20 19:21:34 +03:00
|
|
|
for (auto& cloneInfo : mCloneInfos) {
|
|
|
|
const auto& preprocessHelper = cloneInfo.mPreprocessHelper;
|
2016-10-26 07:51:33 +03:00
|
|
|
|
|
|
|
if (preprocessHelper) {
|
|
|
|
preprocessHelper->ClearActor();
|
|
|
|
}
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
2019-11-20 19:21:34 +03:00
|
|
|
mCloneInfos.Clear();
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
if (mTransaction) {
|
|
|
|
mTransaction->AssertIsOnOwningThread();
|
|
|
|
|
2019-11-05 17:40:37 +03:00
|
|
|
mTransaction->OnRequestFinished(/* aRequestCompletedSuccessfully */
|
2015-03-19 00:20:59 +03:00
|
|
|
aWhy == Deletion);
|
|
|
|
#ifdef DEBUG
|
|
|
|
mTransaction = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundRequestChild::Recv__delete__(
|
2020-03-03 16:50:48 +03:00
|
|
|
RequestResponse&& aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (mTransaction->IsAborted()) {
|
2015-03-19 00:20:59 +03:00
|
|
|
// Always fire an "error" event with ABORT_ERR if the transaction was
|
|
|
|
// aborted, even if the request succeeded or failed with another error.
|
|
|
|
HandleResponse(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
|
|
|
} else {
|
|
|
|
switch (aResponse.type()) {
|
|
|
|
case RequestResponse::Tnsresult:
|
|
|
|
HandleResponse(aResponse.get_nsresult());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TObjectStoreAddResponse:
|
|
|
|
HandleResponse(aResponse.get_ObjectStoreAddResponse().key());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TObjectStorePutResponse:
|
|
|
|
HandleResponse(aResponse.get_ObjectStorePutResponse().key());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TObjectStoreGetResponse:
|
2020-03-03 16:50:48 +03:00
|
|
|
HandleResponse(
|
|
|
|
std::move(aResponse.get_ObjectStoreGetResponse().cloneInfo()));
|
2015-03-19 00:20:59 +03:00
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2016-07-21 11:31:59 +03:00
|
|
|
case RequestResponse::TObjectStoreGetKeyResponse:
|
|
|
|
HandleResponse(aResponse.get_ObjectStoreGetKeyResponse().key());
|
|
|
|
break;
|
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TObjectStoreGetAllResponse:
|
2020-03-03 16:50:48 +03:00
|
|
|
HandleResponse(
|
|
|
|
std::move(aResponse.get_ObjectStoreGetAllResponse().cloneInfos()));
|
2015-03-19 00:20:59 +03:00
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TObjectStoreGetAllKeysResponse:
|
|
|
|
HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse().keys());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TObjectStoreDeleteResponse:
|
|
|
|
case RequestResponse::TObjectStoreClearResponse:
|
|
|
|
HandleResponse(JS::UndefinedHandleValue);
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TObjectStoreCountResponse:
|
|
|
|
HandleResponse(aResponse.get_ObjectStoreCountResponse().count());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TIndexGetResponse:
|
2020-03-03 16:50:48 +03:00
|
|
|
HandleResponse(std::move(aResponse.get_IndexGetResponse().cloneInfo()));
|
2015-03-19 00:20:59 +03:00
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TIndexGetKeyResponse:
|
|
|
|
HandleResponse(aResponse.get_IndexGetKeyResponse().key());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TIndexGetAllResponse:
|
2020-03-03 16:50:48 +03:00
|
|
|
HandleResponse(
|
|
|
|
std::move(aResponse.get_IndexGetAllResponse().cloneInfos()));
|
2015-03-19 00:20:59 +03:00
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TIndexGetAllKeysResponse:
|
|
|
|
HandleResponse(aResponse.get_IndexGetAllKeysResponse().keys());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
case RequestResponse::TIndexCountResponse:
|
|
|
|
HandleResponse(aResponse.get_IndexCountResponse().count());
|
|
|
|
break;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-03-19 00:20:59 +03:00
|
|
|
default:
|
2022-03-03 11:33:15 +03:00
|
|
|
return IPC_FAIL(this, "Unknown response type!");
|
2015-03-19 00:20:59 +03:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2019-11-05 17:40:37 +03:00
|
|
|
mTransaction->OnRequestFinished(/* aRequestCompletedSuccessfully */ true);
|
2015-03-19 00:20:59 +03:00
|
|
|
|
|
|
|
// Null this out so that we don't try to call OnRequestFinished() again in
|
|
|
|
// ActorDestroy.
|
|
|
|
mTransaction = nullptr;
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2016-10-25 22:19:06 +03:00
|
|
|
mozilla::ipc::IPCResult BackgroundRequestChild::RecvPreprocess(
|
|
|
|
const PreprocessParams& aParams) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
nsresult rv;
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
switch (aParams.type()) {
|
|
|
|
case PreprocessParams::TObjectStoreGetPreprocessParams: {
|
2019-11-20 16:19:39 +03:00
|
|
|
const auto& params = aParams.get_ObjectStoreGetPreprocessParams();
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
rv = HandlePreprocess(params.preprocessInfo());
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
break;
|
|
|
|
}
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
case PreprocessParams::TObjectStoreGetAllPreprocessParams: {
|
2019-11-20 16:19:39 +03:00
|
|
|
const auto& params = aParams.get_ObjectStoreGetAllPreprocessParams();
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2016-10-26 07:51:33 +03:00
|
|
|
rv = HandlePreprocess(params.preprocessInfos());
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Unknown params type!");
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2016-11-15 06:26:00 +03:00
|
|
|
if (!SendContinue(rv)) {
|
|
|
|
return IPC_FAIL_NO_REASON(this);
|
|
|
|
}
|
|
|
|
return IPC_OK();
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult BackgroundRequestChild::PreprocessHelper::Init(
|
2020-03-19 14:35:03 +03:00
|
|
|
const StructuredCloneFileChild& aFile) {
|
2016-10-25 22:19:06 +03:00
|
|
|
AssertIsOnOwningThread();
|
2020-03-07 12:31:48 +03:00
|
|
|
MOZ_ASSERT(aFile.HasBlob());
|
2020-03-19 14:35:03 +03:00
|
|
|
MOZ_ASSERT(aFile.Type() == StructuredCloneFileBase::eStructuredClone);
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(mState == State::Initial);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
// The stream transport service is used for asynchronous processing. It has a
|
|
|
|
// threadpool with a high cap of 25 threads. Fortunately, the service can be
|
|
|
|
// used on workers too.
|
|
|
|
nsCOMPtr<nsIEventTarget> target =
|
|
|
|
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
|
|
|
|
MOZ_ASSERT(target);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
// We use a TaskQueue here in order to be sure that the events are dispatched
|
|
|
|
// in the correct order. This is not guaranteed in case we use the I/O thread
|
|
|
|
// directly.
|
2021-12-03 06:16:15 +03:00
|
|
|
mTaskQueue = MakeRefPtr<TaskQueue>(target.forget(), "BackgroundRequestChild");
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
ErrorResult errorResult;
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsCOMPtr<nsIInputStream> stream;
|
2020-03-07 12:31:48 +03:00
|
|
|
// XXX After Bug 1620560, MutableBlob is not needed here anymore.
|
|
|
|
aFile.MutableBlob().CreateInputStream(getter_AddRefs(stream), errorResult);
|
2019-07-03 13:23:33 +03:00
|
|
|
if (NS_WARN_IF(errorResult.Failed())) {
|
|
|
|
return errorResult.StealNSResult();
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
mStream = std::move(stream);
|
|
|
|
|
|
|
|
mCloneData = MakeUnique<JSStructuredCloneData>(
|
|
|
|
JS::StructuredCloneScope::DifferentProcessForIndexedDB);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult BackgroundRequestChild::PreprocessHelper::Dispatch() {
|
|
|
|
AssertIsOnOwningThread();
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(mState == State::Initial);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2020-06-22 16:55:21 +03:00
|
|
|
nsresult rv = mTaskQueue->Dispatch(this, NS_DISPATCH_NORMAL);
|
2016-10-25 22:19:06 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsresult BackgroundRequestChild::PreprocessHelper::Start() {
|
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
|
|
|
MOZ_ASSERT(mStream);
|
|
|
|
MOZ_ASSERT(mState == State::Initial);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsresult rv;
|
2016-10-26 07:51:33 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
PRFileDesc* fileDesc = GetFileDescriptorFromStream(mStream);
|
|
|
|
if (fileDesc) {
|
|
|
|
rv = ProcessStream();
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
2019-07-03 13:23:33 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
mState = State::WaitingForStreamReady;
|
2019-06-04 21:43:02 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsCOMPtr<nsIAsyncFileMetadata> asyncFileMetadata = do_QueryInterface(mStream);
|
|
|
|
if (asyncFileMetadata) {
|
2020-06-22 16:55:21 +03:00
|
|
|
rv = asyncFileMetadata->AsyncFileMetadataWait(this, mTaskQueue);
|
2019-07-03 13:23:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2019-06-04 21:43:02 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
return NS_OK;
|
2019-06-04 21:43:02 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mStream);
|
|
|
|
if (!asyncStream) {
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
2019-06-04 21:43:02 +03:00
|
|
|
}
|
|
|
|
|
2020-06-22 16:55:21 +03:00
|
|
|
rv = asyncStream->AsyncWait(this, 0, 0, mTaskQueue);
|
2019-07-03 13:23:33 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
2019-06-04 21:43:02 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
return NS_OK;
|
2019-06-04 21:43:02 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsresult BackgroundRequestChild::PreprocessHelper::ProcessStream() {
|
2016-10-25 22:19:06 +03:00
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(mStream);
|
|
|
|
MOZ_ASSERT(mState == State::Initial ||
|
|
|
|
mState == State::WaitingForStreamReady);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
// We need to get the internal stream (which is an nsFileInputStream) because
|
|
|
|
// SnappyUncompressInputStream doesn't support reading from async input
|
|
|
|
// streams.
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2020-06-29 14:02:53 +03:00
|
|
|
nsCOMPtr<mozIRemoteLazyInputStream> blobInputStream =
|
|
|
|
do_QueryInterface(mStream);
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(blobInputStream);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
nsCOMPtr<nsIInputStream> internalInputStream =
|
|
|
|
blobInputStream->GetInternalStream();
|
|
|
|
MOZ_ASSERT(internalInputStream);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2021-09-24 16:08:30 +03:00
|
|
|
QM_TRY(MOZ_TO_RESULT(
|
|
|
|
SnappyUncompressStructuredCloneData(*internalInputStream, *mCloneData)));
|
2017-09-08 17:06:26 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
mState = State::Finishing;
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2021-09-24 16:08:30 +03:00
|
|
|
QM_TRY(MOZ_TO_RESULT(mOwningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL)));
|
2016-10-25 22:19:06 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
void BackgroundRequestChild::PreprocessHelper::Finish() {
|
|
|
|
AssertIsOnOwningThread();
|
2017-05-23 08:52:47 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
if (mActor) {
|
|
|
|
if (NS_SUCCEEDED(mResultCode)) {
|
|
|
|
mActor->OnPreprocessFinished(mCloneDataIndex, std::move(mCloneData));
|
2017-05-23 08:52:47 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(!mCloneData);
|
|
|
|
} else {
|
|
|
|
mActor->OnPreprocessFailed(mCloneDataIndex, mResultCode);
|
|
|
|
}
|
2017-05-23 08:52:47 +03:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
mState = State::Completed;
|
2017-05-23 08:52:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED(BackgroundRequestChild::PreprocessHelper,
|
2020-12-03 12:04:44 +03:00
|
|
|
DiscardableRunnable, nsIInputStreamCallback,
|
2017-09-08 17:06:26 +03:00
|
|
|
nsIFileMetadataCallback)
|
2017-05-23 08:52:47 +03:00
|
|
|
|
2016-10-25 22:19:06 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
BackgroundRequestChild::PreprocessHelper::Run() {
|
2019-07-03 13:23:33 +03:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
switch (mState) {
|
|
|
|
case State::Initial:
|
|
|
|
rv = Start();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case State::WaitingForStreamReady:
|
|
|
|
rv = ProcessStream();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case State::Finishing:
|
|
|
|
Finish();
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Bad state!");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv)) && mState != State::Finishing) {
|
|
|
|
if (NS_SUCCEEDED(mResultCode)) {
|
|
|
|
mResultCode = rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Must set mState before dispatching otherwise we will race with the owning
|
|
|
|
// thread.
|
|
|
|
mState = State::Finishing;
|
|
|
|
|
|
|
|
if (IsOnOwningThread()) {
|
|
|
|
Finish();
|
|
|
|
} else {
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
|
|
mOwningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL));
|
|
|
|
}
|
2017-05-23 08:52:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
BackgroundRequestChild::PreprocessHelper::OnInputStreamReady(
|
|
|
|
nsIAsyncInputStream* aStream) {
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
|
|
|
MOZ_ASSERT(mState == State::WaitingForStreamReady);
|
|
|
|
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(this->Run());
|
|
|
|
|
|
|
|
return NS_OK;
|
2017-09-08 17:06:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
BackgroundRequestChild::PreprocessHelper::OnFileMetadataReady(
|
|
|
|
nsIAsyncFileMetadata* aObject) {
|
2017-05-23 08:52:47 +03:00
|
|
|
MOZ_ASSERT(!IsOnOwningThread());
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ASSERT(mState == State::WaitingForStreamReady);
|
2016-10-25 22:19:06 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(this->Run());
|
2017-05-23 08:52:47 +03:00
|
|
|
|
2019-07-03 13:23:33 +03:00
|
|
|
return NS_OK;
|
2016-10-25 22:19:06 +03:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundCursorChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
BackgroundCursorChildBase::BackgroundCursorChildBase(
|
|
|
|
const NotNull<IDBRequest*> aRequest, const Direction aDirection)
|
|
|
|
: mRequest(aRequest),
|
2020-04-21 17:32:51 +03:00
|
|
|
mTransaction(aRequest->MaybeTransactionRef()),
|
2014-09-27 03:21:57 +04:00
|
|
|
mStrongRequest(aRequest),
|
2020-01-10 18:23:52 +03:00
|
|
|
mDirection(aDirection) {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
}
|
|
|
|
|
2020-07-01 23:14:23 +03:00
|
|
|
MovingNotNull<RefPtr<IDBRequest>> BackgroundCursorChildBase::AcquireRequest()
|
|
|
|
const {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
// XXX This could be encapsulated by NotNull
|
|
|
|
return WrapNotNullUnchecked(RefPtr{mRequest->get()});
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
2020-07-01 23:14:23 +03:00
|
|
|
BackgroundCursorChild<CursorType>::BackgroundCursorChild(
|
|
|
|
const NotNull<IDBRequest*> aRequest, SourceType* aSource,
|
|
|
|
Direction aDirection)
|
2020-01-10 18:23:52 +03:00
|
|
|
: BackgroundCursorChildBase(aRequest, aDirection),
|
2020-05-14 12:14:04 +03:00
|
|
|
mSource(WrapNotNull(aSource)),
|
2014-09-27 03:21:57 +04:00
|
|
|
mCursor(nullptr),
|
2019-11-14 19:14:02 +03:00
|
|
|
mInFlightResponseInvalidationNeeded(false) {
|
2020-01-10 18:23:52 +03:00
|
|
|
aSource->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild<CursorType>);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
BackgroundCursorChild<CursorType>::~BackgroundCursorChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundCursorChild<CursorType>);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-08-28 18:50:38 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
SafeRefPtr<BackgroundCursorChild<CursorType>>
|
|
|
|
BackgroundCursorChild<CursorType>::SafeRefPtrFromThis() {
|
|
|
|
return BackgroundCursorChildBase::SafeRefPtrFromThis()
|
|
|
|
.template downcast<BackgroundCursorChild>();
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
void BackgroundCursorChild<CursorType>::SendContinueInternal(
|
|
|
|
const CursorRequestParams& aParams,
|
|
|
|
const CursorData<CursorType>& aCurrentData) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mRequest);
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
MOZ_ASSERT(mCursor);
|
|
|
|
MOZ_ASSERT(!mStrongRequest);
|
|
|
|
MOZ_ASSERT(!mStrongCursor);
|
|
|
|
|
|
|
|
// Make sure all our DOM objects stay alive.
|
|
|
|
mStrongCursor = mCursor;
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
MOZ_ASSERT(GetRequest()->ReadyState() == IDBRequestReadyState::Done);
|
|
|
|
GetRequest()->Reset();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
mTransaction->OnNewRequest();
|
|
|
|
|
2019-11-05 17:40:37 +03:00
|
|
|
CursorRequestParams params = aParams;
|
2020-01-10 18:23:52 +03:00
|
|
|
Key currentKey = aCurrentData.mKey;
|
|
|
|
Key currentObjectStoreKey;
|
|
|
|
// TODO: This is still not nice.
|
|
|
|
if constexpr (!CursorTypeTraits<CursorType>::IsObjectStoreCursor) {
|
|
|
|
currentObjectStoreKey = aCurrentData.mObjectStoreKey;
|
|
|
|
}
|
2019-11-05 17:40:37 +03:00
|
|
|
|
|
|
|
switch (params.type()) {
|
|
|
|
case CursorRequestParams::TContinueParams: {
|
|
|
|
const auto& key = params.get_ContinueParams().key();
|
|
|
|
if (key.IsUnset()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-11-05 19:46:10 +03:00
|
|
|
// Discard cache entries before the target key.
|
|
|
|
DiscardCachedResponses(
|
|
|
|
[&key, isLocaleAware = mCursor->IsLocaleAware(),
|
|
|
|
keyOperator = GetKeyOperator(mDirection),
|
|
|
|
transactionSerialNumber = mTransaction->LoggingSerialNumber(),
|
2020-01-10 18:23:52 +03:00
|
|
|
requestSerialNumber = GetRequest()->LoggingSerialNumber()](
|
2019-11-05 19:46:10 +03:00
|
|
|
const auto& currentCachedResponse) {
|
|
|
|
// This duplicates the logic from the parent. We could avoid this
|
|
|
|
// duplication if we invalidated the cached records always for any
|
|
|
|
// continue-with-key operation, but would lose the benefits of
|
|
|
|
// preloading then.
|
|
|
|
const auto& cachedSortKey =
|
2020-01-10 18:23:52 +03:00
|
|
|
currentCachedResponse.GetSortKey(isLocaleAware);
|
2019-11-05 19:46:10 +03:00
|
|
|
const bool discard = !(cachedSortKey.*keyOperator)(key);
|
|
|
|
if (discard) {
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
|
|
|
"PRELOAD: Continue to key %s, discarding cached key %s/%s",
|
2020-07-03 12:39:24 +03:00
|
|
|
"Continue, discarding%.0s%.0s%.0s", transactionSerialNumber,
|
2019-11-05 19:46:10 +03:00
|
|
|
requestSerialNumber, key.GetBuffer().get(),
|
|
|
|
cachedSortKey.GetBuffer().get(),
|
2020-01-10 18:23:52 +03:00
|
|
|
currentCachedResponse.GetObjectStoreKeyForLogging());
|
2019-11-05 19:46:10 +03:00
|
|
|
} else {
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
|
|
|
"PRELOAD: Continue to key %s, keeping cached key %s/%s and "
|
|
|
|
"further",
|
2020-07-03 12:39:24 +03:00
|
|
|
"Continue, keeping%.0s%.0s%.0s", transactionSerialNumber,
|
2019-11-05 19:46:10 +03:00
|
|
|
requestSerialNumber, key.GetBuffer().get(),
|
|
|
|
cachedSortKey.GetBuffer().get(),
|
2020-01-10 18:23:52 +03:00
|
|
|
currentCachedResponse.GetObjectStoreKeyForLogging());
|
2019-11-05 19:46:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return discard;
|
|
|
|
});
|
|
|
|
|
2019-11-05 17:40:37 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-11-26 16:33:56 +03:00
|
|
|
case CursorRequestParams::TContinuePrimaryKeyParams: {
|
2020-01-10 18:23:52 +03:00
|
|
|
if constexpr (!CursorTypeTraits<CursorType>::IsObjectStoreCursor) {
|
|
|
|
const auto& key = params.get_ContinuePrimaryKeyParams().key();
|
|
|
|
const auto& primaryKey =
|
|
|
|
params.get_ContinuePrimaryKeyParams().primaryKey();
|
|
|
|
if (key.IsUnset() || primaryKey.IsUnset()) {
|
|
|
|
break;
|
|
|
|
}
|
2020-01-10 18:19:22 +03:00
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
// Discard cache entries before the target key.
|
|
|
|
DiscardCachedResponses([&key, &primaryKey,
|
|
|
|
isLocaleAware = mCursor->IsLocaleAware(),
|
|
|
|
keyCompareOperator = GetKeyOperator(mDirection),
|
|
|
|
transactionSerialNumber =
|
|
|
|
mTransaction->LoggingSerialNumber(),
|
|
|
|
requestSerialNumber =
|
|
|
|
GetRequest()->LoggingSerialNumber()](
|
|
|
|
const auto& currentCachedResponse) {
|
|
|
|
// This duplicates the logic from the parent. We could avoid this
|
|
|
|
// duplication if we invalidated the cached records always for any
|
|
|
|
// continue-with-key operation, but would lose the benefits of
|
|
|
|
// preloading then.
|
|
|
|
const auto& cachedSortKey =
|
|
|
|
currentCachedResponse.GetSortKey(isLocaleAware);
|
|
|
|
const auto& cachedSortPrimaryKey =
|
|
|
|
currentCachedResponse.mObjectStoreKey;
|
|
|
|
|
|
|
|
const bool discard =
|
|
|
|
(cachedSortKey == key &&
|
|
|
|
!(cachedSortPrimaryKey.*keyCompareOperator)(primaryKey)) ||
|
|
|
|
!(cachedSortKey.*keyCompareOperator)(key);
|
|
|
|
|
|
|
|
if (discard) {
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
|
|
|
"PRELOAD: Continue to key %s with primary key %s, discarding "
|
|
|
|
"cached key %s with cached primary key %s",
|
2020-07-03 12:39:24 +03:00
|
|
|
"Continue, discarding%.0s%.0s%.0s%.0s", transactionSerialNumber,
|
2020-01-10 18:23:52 +03:00
|
|
|
requestSerialNumber, key.GetBuffer().get(),
|
|
|
|
primaryKey.GetBuffer().get(), cachedSortKey.GetBuffer().get(),
|
|
|
|
cachedSortPrimaryKey.GetBuffer().get());
|
|
|
|
} else {
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
|
|
|
"PRELOAD: Continue to key %s with primary key %s, keeping "
|
|
|
|
"cached key %s with cached primary key %s and further",
|
2020-07-03 12:39:24 +03:00
|
|
|
"Continue, keeping%.0s%.0s%.0s%.0s", transactionSerialNumber,
|
2020-01-10 18:23:52 +03:00
|
|
|
requestSerialNumber, key.GetBuffer().get(),
|
|
|
|
primaryKey.GetBuffer().get(), cachedSortKey.GetBuffer().get(),
|
|
|
|
cachedSortPrimaryKey.GetBuffer().get());
|
|
|
|
}
|
2020-01-10 18:19:22 +03:00
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
return discard;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
MOZ_CRASH("Shouldn't get here");
|
|
|
|
}
|
2019-11-26 16:33:56 +03:00
|
|
|
|
2019-11-05 17:40:37 +03:00
|
|
|
break;
|
2019-11-26 16:33:56 +03:00
|
|
|
}
|
2019-11-05 17:40:37 +03:00
|
|
|
|
|
|
|
case CursorRequestParams::TAdvanceParams: {
|
|
|
|
uint32_t& advanceCount = params.get_AdvanceParams().count();
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2020-07-03 12:39:24 +03:00
|
|
|
"PRELOAD: Advancing %" PRIu32 " records", "Advancing %" PRIu32,
|
2020-01-10 18:23:52 +03:00
|
|
|
mTransaction->LoggingSerialNumber(),
|
|
|
|
GetRequest()->LoggingSerialNumber(), advanceCount);
|
2019-11-05 17:40:37 +03:00
|
|
|
|
2019-11-05 19:46:10 +03:00
|
|
|
// Discard cache entries.
|
2020-01-10 18:23:52 +03:00
|
|
|
DiscardCachedResponses([&advanceCount, ¤tKey,
|
|
|
|
¤tObjectStoreKey](
|
|
|
|
const auto& currentCachedResponse) {
|
|
|
|
const bool res = advanceCount > 1;
|
|
|
|
if (res) {
|
|
|
|
--advanceCount;
|
|
|
|
|
|
|
|
// TODO: We only need to update currentKey on the last entry, the
|
|
|
|
// others are overwritten in the next iteration anyway.
|
|
|
|
currentKey = currentCachedResponse.mKey;
|
|
|
|
if constexpr (!CursorTypeTraits<CursorType>::IsObjectStoreCursor) {
|
|
|
|
currentObjectStoreKey = currentCachedResponse.mObjectStoreKey;
|
|
|
|
} else {
|
|
|
|
Unused << currentObjectStoreKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
});
|
2019-11-05 17:40:37 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Should never get here!");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mCachedResponses.empty()) {
|
|
|
|
// We need to remove the response here from mCachedResponses, since when
|
|
|
|
// requests are interleaved, other events may be processed before
|
|
|
|
// CompleteContinueRequestFromCache, which may modify mCachedResponses.
|
|
|
|
mDelayedResponses.emplace_back(std::move(mCachedResponses.front()));
|
|
|
|
mCachedResponses.pop_front();
|
|
|
|
|
|
|
|
// We cannot send the response right away, as we must preserve the request
|
|
|
|
// order. Dispatching a DelayedActionRunnable only partially addresses this.
|
|
|
|
// This is accompanied by invalidating cached entries at proper locations to
|
|
|
|
// make it correct. To avoid this, further changes are necessary, see Bug
|
|
|
|
// 1580499.
|
2020-01-10 18:23:52 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(
|
|
|
|
MakeAndAddRef<DelayedActionRunnable<BackgroundCursorChild<CursorType>>>(
|
2020-08-28 18:50:38 +03:00
|
|
|
SafeRefPtrFromThis(),
|
|
|
|
&BackgroundCursorChild::CompleteContinueRequestFromCache)));
|
2019-11-05 17:40:37 +03:00
|
|
|
|
|
|
|
// TODO: Could we preload further entries in the background when the size of
|
|
|
|
// mCachedResponses falls under some threshold? Or does the response
|
|
|
|
// handling model disallow this?
|
|
|
|
} else {
|
2019-11-05 17:40:35 +03:00
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundIDBCursorChild::SendContinue(
|
|
|
|
params, currentKey, currentObjectStoreKey));
|
2019-11-05 17:40:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
void BackgroundCursorChild<CursorType>::CompleteContinueRequestFromCache() {
|
2019-11-05 17:40:37 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
MOZ_ASSERT(mCursor);
|
|
|
|
MOZ_ASSERT(mStrongCursor);
|
|
|
|
MOZ_ASSERT(!mDelayedResponses.empty());
|
2020-01-10 18:23:52 +03:00
|
|
|
MOZ_ASSERT(mCursor->GetType() == CursorType);
|
2019-11-05 17:40:37 +03:00
|
|
|
|
2020-01-09 17:43:57 +03:00
|
|
|
const RefPtr<IDBCursor> cursor = std::move(mStrongCursor);
|
2019-11-05 17:40:37 +03:00
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
mCursor->Reset(std::move(mDelayedResponses.front()));
|
2019-11-05 17:40:37 +03:00
|
|
|
mDelayedResponses.pop_front();
|
|
|
|
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
|
|
|
"PRELOAD: Consumed 1 cached response, %zu cached responses remaining",
|
2020-07-03 12:39:24 +03:00
|
|
|
"Consumed cached response, %zu remaining",
|
|
|
|
mTransaction->LoggingSerialNumber(), GetRequest()->LoggingSerialNumber(),
|
2019-11-05 17:40:37 +03:00
|
|
|
mDelayedResponses.size() + mCachedResponses.size());
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(
|
|
|
|
GetRequest(),
|
|
|
|
mTransaction
|
|
|
|
? SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}}
|
|
|
|
: nullptr,
|
2020-07-01 23:14:23 +03:00
|
|
|
*cursor);
|
2019-11-05 17:40:37 +03:00
|
|
|
|
|
|
|
mTransaction->OnRequestFinished(/* aRequestCompletedSuccessfully */ true);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
void BackgroundCursorChild<CursorType>::SendDeleteMeInternal() {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!mStrongRequest);
|
|
|
|
MOZ_ASSERT(!mStrongCursor);
|
|
|
|
|
2020-04-01 12:53:39 +03:00
|
|
|
mRequest.destroy();
|
2020-04-21 17:32:51 +03:00
|
|
|
mTransaction = Nothing();
|
2020-01-10 18:23:52 +03:00
|
|
|
// TODO: The things until here could be pulled up to
|
|
|
|
// BackgroundCursorChildBase.
|
|
|
|
|
2020-04-01 12:53:39 +03:00
|
|
|
mSource.destroy();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
if (mCursor) {
|
|
|
|
mCursor->ClearBackgroundActor();
|
|
|
|
mCursor = nullptr;
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundIDBCursorChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
void BackgroundCursorChild<CursorType>::InvalidateCachedResponses() {
|
2019-11-05 17:40:37 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
MOZ_ASSERT(mRequest);
|
|
|
|
|
|
|
|
// TODO: With more information on the reason for the invalidation, we might
|
|
|
|
// only selectively invalidate cached responses. If the reason is an updated
|
|
|
|
// value, we do not need to care for key-only cursors. If the key of the
|
|
|
|
// changed entry is not in the remaining range of the cursor, we also do not
|
|
|
|
// need to care, etc.
|
|
|
|
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2020-07-03 12:39:24 +03:00
|
|
|
"PRELOAD: Invalidating all %zu cached responses", "Invalidating %zu",
|
2020-01-10 18:23:52 +03:00
|
|
|
mTransaction->LoggingSerialNumber(), GetRequest()->LoggingSerialNumber(),
|
2019-11-05 17:40:37 +03:00
|
|
|
mCachedResponses.size());
|
|
|
|
|
|
|
|
mCachedResponses.clear();
|
2019-11-14 19:14:02 +03:00
|
|
|
|
|
|
|
// We only hold a strong cursor reference in mStrongCursor when
|
|
|
|
// continue()/similar has been called. In those cases we expect a response
|
|
|
|
// that will be received in the future, and it may include prefetched data
|
|
|
|
// that needs to be discarded.
|
|
|
|
if (mStrongCursor) {
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
|
|
|
"PRELOAD: Setting flag to invalidate in-flight responses",
|
|
|
|
"Set flag to invalidate in-flight responses",
|
2020-01-10 18:23:52 +03:00
|
|
|
mTransaction->LoggingSerialNumber(),
|
|
|
|
GetRequest()->LoggingSerialNumber());
|
2019-11-14 19:14:02 +03:00
|
|
|
|
|
|
|
mInFlightResponseInvalidationNeeded = true;
|
|
|
|
}
|
2019-11-05 17:40:37 +03:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
2019-11-05 19:46:10 +03:00
|
|
|
template <typename Condition>
|
2020-01-10 18:23:52 +03:00
|
|
|
void BackgroundCursorChild<CursorType>::DiscardCachedResponses(
|
2019-11-05 19:46:10 +03:00
|
|
|
const Condition& aConditionFunc) {
|
|
|
|
size_t discardedCount = 0;
|
|
|
|
while (!mCachedResponses.empty() &&
|
|
|
|
aConditionFunc(mCachedResponses.front())) {
|
|
|
|
mCachedResponses.pop_front();
|
|
|
|
++discardedCount;
|
|
|
|
}
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2020-07-03 12:39:24 +03:00
|
|
|
"PRELOAD: Discarded %zu cached responses, %zu remaining",
|
|
|
|
"Discarded %zu; remaining %zu", mTransaction->LoggingSerialNumber(),
|
|
|
|
GetRequest()->LoggingSerialNumber(), discardedCount,
|
|
|
|
mCachedResponses.size());
|
2019-11-05 19:46:10 +03:00
|
|
|
}
|
|
|
|
|
2020-08-28 18:50:23 +03:00
|
|
|
BackgroundCursorChildBase::~BackgroundCursorChildBase() = default;
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
void BackgroundCursorChildBase::HandleResponse(nsresult aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(NS_FAILED(aResponse));
|
|
|
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
|
|
|
MOZ_ASSERT(mRequest);
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
MOZ_ASSERT(!mStrongRequest);
|
|
|
|
MOZ_ASSERT(!mStrongCursor);
|
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
DispatchErrorEvent(
|
|
|
|
GetRequest(), aResponse,
|
|
|
|
SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}});
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
void BackgroundCursorChild<CursorType>::HandleResponse(
|
|
|
|
const void_t& aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mRequest);
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
MOZ_ASSERT(!mStrongRequest);
|
|
|
|
MOZ_ASSERT(!mStrongCursor);
|
|
|
|
|
|
|
|
if (mCursor) {
|
|
|
|
mCursor->Reset();
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(
|
|
|
|
GetRequest(),
|
|
|
|
mTransaction
|
|
|
|
? SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}}
|
|
|
|
: nullptr,
|
2020-07-01 23:14:23 +03:00
|
|
|
JS::NullHandleValue);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
if (!mCursor) {
|
2017-01-13 11:40:58 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(this->GetActorEventTarget()->Dispatch(
|
2020-01-10 18:23:52 +03:00
|
|
|
MakeAndAddRef<DelayedActionRunnable<BackgroundCursorChild<CursorType>>>(
|
2020-08-28 18:50:38 +03:00
|
|
|
SafeRefPtrFromThis(), &BackgroundCursorChild::SendDeleteMeInternal),
|
2019-12-13 15:18:21 +03:00
|
|
|
NS_DISPATCH_NORMAL));
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
2019-11-05 19:46:23 +03:00
|
|
|
template <typename... Args>
|
2020-01-10 18:23:52 +03:00
|
|
|
RefPtr<IDBCursor>
|
|
|
|
BackgroundCursorChild<CursorType>::HandleIndividualCursorResponse(
|
2019-11-05 19:46:31 +03:00
|
|
|
const bool aUseAsCurrentResult, Args&&... aArgs) {
|
2019-11-05 19:46:23 +03:00
|
|
|
if (mCursor) {
|
2019-11-05 19:46:31 +03:00
|
|
|
if (aUseAsCurrentResult) {
|
2020-01-10 18:23:52 +03:00
|
|
|
mCursor->Reset(CursorData<CursorType>{std::forward<Args>(aArgs)...});
|
2019-11-05 19:46:23 +03:00
|
|
|
} else {
|
|
|
|
mCachedResponses.emplace_back(std::forward<Args>(aArgs)...);
|
|
|
|
}
|
2019-11-26 17:38:16 +03:00
|
|
|
return nullptr;
|
2019-11-05 19:46:23 +03:00
|
|
|
}
|
2019-11-26 17:38:16 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(aUseAsCurrentResult);
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
// TODO: This still looks quite dangerous to me. Why is mCursor not a
|
|
|
|
// RefPtr?
|
|
|
|
auto newCursor = IDBCursor::Create(this, std::forward<Args>(aArgs)...);
|
2019-11-26 17:38:16 +03:00
|
|
|
mCursor = newCursor;
|
|
|
|
return newCursor;
|
2019-11-05 19:46:23 +03:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
2020-03-17 14:28:49 +03:00
|
|
|
template <typename Func>
|
2020-01-10 18:23:52 +03:00
|
|
|
void BackgroundCursorChild<CursorType>::HandleMultipleCursorResponses(
|
2020-03-17 14:28:49 +03:00
|
|
|
nsTArray<ResponseType>&& aResponses, const Func& aHandleRecord) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mRequest);
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
MOZ_ASSERT(!mStrongRequest);
|
|
|
|
MOZ_ASSERT(!mStrongCursor);
|
2019-11-05 17:40:35 +03:00
|
|
|
MOZ_ASSERT(aResponses.Length() > 0);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2019-11-05 17:40:37 +03:00
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2020-07-03 12:39:24 +03:00
|
|
|
"PRELOAD: Received %zu cursor responses", "Received %zu",
|
2020-01-10 18:23:52 +03:00
|
|
|
mTransaction->LoggingSerialNumber(), GetRequest()->LoggingSerialNumber(),
|
2019-11-05 17:40:37 +03:00
|
|
|
aResponses.Length());
|
|
|
|
MOZ_ASSERT_IF(aResponses.Length() > 1, mCachedResponses.empty());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2019-11-26 17:38:16 +03:00
|
|
|
// If a new cursor is created, we need to keep a reference to it until the
|
2020-05-14 12:42:23 +03:00
|
|
|
// SetResultAndDispatchSuccessEvent creates a DOM Binding.
|
2019-11-26 17:38:16 +03:00
|
|
|
RefPtr<IDBCursor> strongNewCursor;
|
|
|
|
|
2019-11-05 19:46:31 +03:00
|
|
|
bool isFirst = true;
|
2020-03-03 16:51:18 +03:00
|
|
|
for (auto& response : aResponses) {
|
2019-11-05 17:40:35 +03:00
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2020-07-03 12:39:24 +03:00
|
|
|
"PRELOAD: Processing response for key %s", "Processing%.0s",
|
2020-01-10 18:23:52 +03:00
|
|
|
mTransaction->LoggingSerialNumber(),
|
|
|
|
GetRequest()->LoggingSerialNumber(), response.key().GetBuffer().get());
|
2019-11-05 17:34:22 +03:00
|
|
|
|
2019-11-05 19:46:31 +03:00
|
|
|
// TODO: At the moment, we only send a cursor request to the parent if
|
2020-01-10 18:23:52 +03:00
|
|
|
// requested by the user code. Therefore, the first result is always used
|
|
|
|
// as the current result, and the potential extra results are cached. If
|
|
|
|
// we extended this towards preloading in the background, all results
|
|
|
|
// might need to be cached.
|
2019-11-26 17:38:16 +03:00
|
|
|
auto maybeNewCursor =
|
2020-03-03 16:51:18 +03:00
|
|
|
aHandleRecord(/* aUseAsCurrentResult */ isFirst, std::move(response));
|
2019-11-26 17:38:16 +03:00
|
|
|
if (maybeNewCursor) {
|
|
|
|
MOZ_ASSERT(!strongNewCursor);
|
|
|
|
strongNewCursor = std::move(maybeNewCursor);
|
|
|
|
}
|
2019-11-05 19:46:31 +03:00
|
|
|
isFirst = false;
|
2019-11-14 19:14:02 +03:00
|
|
|
|
|
|
|
if (mInFlightResponseInvalidationNeeded) {
|
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
|
|
|
"PRELOAD: Discarding remaining responses since "
|
|
|
|
"mInFlightResponseInvalidationNeeded is set",
|
|
|
|
"Discarding responses", mTransaction->LoggingSerialNumber(),
|
2020-01-10 18:23:52 +03:00
|
|
|
GetRequest()->LoggingSerialNumber());
|
2019-11-14 19:14:02 +03:00
|
|
|
|
|
|
|
mInFlightResponseInvalidationNeeded = false;
|
|
|
|
break;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:42:23 +03:00
|
|
|
SetResultAndDispatchSuccessEvent(
|
|
|
|
GetRequest(),
|
|
|
|
mTransaction
|
|
|
|
? SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}}
|
|
|
|
: nullptr,
|
2020-07-01 23:14:23 +03:00
|
|
|
*static_cast<IDBCursor*>(mCursor));
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
void BackgroundCursorChild<CursorType>::HandleResponse(
|
2020-03-17 14:28:49 +03:00
|
|
|
nsTArray<ResponseType>&& aResponses) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-11-10 20:05:36 +03:00
|
|
|
if constexpr (CursorType == IDBCursorType::ObjectStore ||
|
|
|
|
CursorType == IDBCursorType::Index) {
|
2020-03-17 14:28:49 +03:00
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
|
2020-11-10 20:05:36 +03:00
|
|
|
if (!mTransaction->Database()->GetOwnerGlobal()) {
|
|
|
|
// Ignore the response, since we have already been disconnected from the
|
|
|
|
// global.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if constexpr (CursorType == IDBCursorType::ObjectStore) {
|
2020-03-17 14:28:49 +03:00
|
|
|
HandleMultipleCursorResponses(
|
|
|
|
std::move(aResponses), [this](const bool useAsCurrentResult,
|
|
|
|
ObjectStoreCursorResponse&& response) {
|
|
|
|
// TODO: Maybe move the deserialization of the clone-read-info into
|
|
|
|
// the cursor, so that it is only done for records actually accessed,
|
|
|
|
// which might not be the case for all cached records.
|
|
|
|
return HandleIndividualCursorResponse(
|
|
|
|
useAsCurrentResult, std::move(response.key()),
|
|
|
|
DeserializeStructuredCloneReadInfo(
|
|
|
|
std::move(response.cloneInfo()), mTransaction->Database(),
|
|
|
|
PreprocessingNotSupported));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if constexpr (CursorType == IDBCursorType::ObjectStoreKey) {
|
|
|
|
HandleMultipleCursorResponses(
|
|
|
|
std::move(aResponses), [this](const bool useAsCurrentResult,
|
|
|
|
ObjectStoreKeyCursorResponse&& response) {
|
|
|
|
return HandleIndividualCursorResponse(useAsCurrentResult,
|
|
|
|
std::move(response.key()));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if constexpr (CursorType == IDBCursorType::Index) {
|
|
|
|
HandleMultipleCursorResponses(
|
|
|
|
std::move(aResponses),
|
|
|
|
[this](const bool useAsCurrentResult, IndexCursorResponse&& response) {
|
|
|
|
return HandleIndividualCursorResponse(
|
|
|
|
useAsCurrentResult, std::move(response.key()),
|
|
|
|
std::move(response.sortKey()), std::move(response.objectKey()),
|
|
|
|
DeserializeStructuredCloneReadInfo(
|
|
|
|
std::move(response.cloneInfo()), mTransaction->Database(),
|
|
|
|
PreprocessingNotSupported));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if constexpr (CursorType == IDBCursorType::IndexKey) {
|
|
|
|
HandleMultipleCursorResponses(
|
|
|
|
std::move(aResponses), [this](const bool useAsCurrentResult,
|
|
|
|
IndexKeyCursorResponse&& response) {
|
|
|
|
return HandleIndividualCursorResponse(
|
|
|
|
useAsCurrentResult, std::move(response.key()),
|
|
|
|
std::move(response.sortKey()), std::move(response.objectKey()));
|
|
|
|
});
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
void BackgroundCursorChild<CursorType>::ActorDestroy(ActorDestroyReason aWhy) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT_IF(aWhy == Deletion, !mStrongRequest);
|
|
|
|
MOZ_ASSERT_IF(aWhy == Deletion, !mStrongCursor);
|
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
|
|
|
if (mStrongRequest && !mStrongCursor && mTransaction) {
|
2019-11-05 17:40:37 +03:00
|
|
|
mTransaction->OnRequestFinished(/* aRequestCompletedSuccessfully */
|
2015-03-19 00:20:59 +03:00
|
|
|
aWhy == Deletion);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mCursor) {
|
|
|
|
mCursor->ClearBackgroundActor();
|
|
|
|
#ifdef DEBUG
|
|
|
|
mCursor = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2020-04-01 12:53:39 +03:00
|
|
|
mRequest.maybeDestroy();
|
2020-04-21 17:32:51 +03:00
|
|
|
mTransaction = Nothing();
|
2020-04-01 12:53:39 +03:00
|
|
|
mSource.maybeDestroy();
|
2014-09-27 03:21:57 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <IDBCursorType CursorType>
|
|
|
|
mozilla::ipc::IPCResult BackgroundCursorChild<CursorType>::RecvResponse(
|
2020-03-03 16:51:18 +03:00
|
|
|
CursorResponse&& aResponse) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aResponse.type() != CursorResponse::T__None);
|
|
|
|
MOZ_ASSERT(mRequest);
|
|
|
|
MOZ_ASSERT(mTransaction);
|
|
|
|
MOZ_ASSERT_IF(mCursor, mStrongCursor);
|
2014-11-08 03:42:53 +03:00
|
|
|
MOZ_ASSERT_IF(!mCursor, mStrongRequest);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
MaybeCollectGarbageOnIPCMessage();
|
|
|
|
|
2020-01-09 17:43:57 +03:00
|
|
|
const RefPtr<IDBRequest> request = std::move(mStrongRequest);
|
|
|
|
Unused << request; // XXX see Bug 1605075
|
|
|
|
const RefPtr<IDBCursor> cursor = std::move(mStrongCursor);
|
|
|
|
Unused << cursor; // XXX see Bug 1605075
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-04-21 17:32:51 +03:00
|
|
|
const auto transaction =
|
|
|
|
SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}};
|
2018-12-20 16:39:46 +03:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
switch (aResponse.type()) {
|
|
|
|
case CursorResponse::Tnsresult:
|
|
|
|
HandleResponse(aResponse.get_nsresult());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CursorResponse::Tvoid_t:
|
|
|
|
HandleResponse(aResponse.get_void_t());
|
|
|
|
break;
|
|
|
|
|
2015-08-20 00:59:25 +03:00
|
|
|
case CursorResponse::TArrayOfObjectStoreCursorResponse:
|
2020-01-10 18:23:52 +03:00
|
|
|
if constexpr (CursorType == IDBCursorType::ObjectStore) {
|
2020-03-03 16:51:18 +03:00
|
|
|
HandleResponse(
|
|
|
|
std::move(aResponse.get_ArrayOfObjectStoreCursorResponse()));
|
2020-01-10 18:23:52 +03:00
|
|
|
} else {
|
|
|
|
MOZ_CRASH("Response type mismatch");
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
break;
|
|
|
|
|
2019-11-05 17:40:31 +03:00
|
|
|
case CursorResponse::TArrayOfObjectStoreKeyCursorResponse:
|
2020-01-10 18:23:52 +03:00
|
|
|
if constexpr (CursorType == IDBCursorType::ObjectStoreKey) {
|
2020-03-03 16:51:18 +03:00
|
|
|
HandleResponse(
|
|
|
|
std::move(aResponse.get_ArrayOfObjectStoreKeyCursorResponse()));
|
2020-01-10 18:23:52 +03:00
|
|
|
} else {
|
|
|
|
MOZ_CRASH("Response type mismatch");
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
break;
|
|
|
|
|
2019-11-05 17:40:35 +03:00
|
|
|
case CursorResponse::TArrayOfIndexCursorResponse:
|
2020-01-10 18:23:52 +03:00
|
|
|
if constexpr (CursorType == IDBCursorType::Index) {
|
2020-03-03 16:51:18 +03:00
|
|
|
HandleResponse(std::move(aResponse.get_ArrayOfIndexCursorResponse()));
|
2020-01-10 18:23:52 +03:00
|
|
|
} else {
|
|
|
|
MOZ_CRASH("Response type mismatch");
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
break;
|
|
|
|
|
2019-11-05 17:40:31 +03:00
|
|
|
case CursorResponse::TArrayOfIndexKeyCursorResponse:
|
2020-01-10 18:23:52 +03:00
|
|
|
if constexpr (CursorType == IDBCursorType::IndexKey) {
|
2020-03-03 16:51:18 +03:00
|
|
|
HandleResponse(
|
|
|
|
std::move(aResponse.get_ArrayOfIndexKeyCursorResponse()));
|
2020-01-10 18:23:52 +03:00
|
|
|
} else {
|
|
|
|
MOZ_CRASH("Response type mismatch");
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Should never get here!");
|
|
|
|
}
|
|
|
|
|
2019-11-05 17:40:37 +03:00
|
|
|
transaction->OnRequestFinished(/* aRequestCompletedSuccessfully */ true);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2020-03-17 14:28:49 +03:00
|
|
|
template class BackgroundCursorChild<IDBCursorType::ObjectStore>;
|
|
|
|
template class BackgroundCursorChild<IDBCursorType::ObjectStoreKey>;
|
|
|
|
template class BackgroundCursorChild<IDBCursorType::Index>;
|
|
|
|
template class BackgroundCursorChild<IDBCursorType::IndexKey>;
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <typename T>
|
|
|
|
NS_IMETHODIMP DelayedActionRunnable<T>::Run() {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mActor);
|
|
|
|
mActor->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mRequest);
|
2015-06-09 17:57:19 +03:00
|
|
|
MOZ_ASSERT(mActionFunc);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2020-08-28 18:50:38 +03:00
|
|
|
((*mActor).*mActionFunc)();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
mActor = nullptr;
|
|
|
|
mRequest = nullptr;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2020-01-10 18:23:52 +03:00
|
|
|
template <typename T>
|
|
|
|
nsresult DelayedActionRunnable<T>::Cancel() {
|
2014-12-17 09:26:15 +03:00
|
|
|
if (NS_WARN_IF(!mActor)) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This must always run to clean up our state.
|
|
|
|
Run();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-06-07 13:36:42 +03:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundFileHandleChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundFileHandleChild::BackgroundFileHandleChild(IDBFileHandle* aFileHandle)
|
|
|
|
: mTemporaryStrongFileHandle(aFileHandle), mFileHandle(aFileHandle) {
|
|
|
|
MOZ_ASSERT(aFileHandle);
|
|
|
|
aFileHandle->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(BackgroundFileHandleChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundFileHandleChild::~BackgroundFileHandleChild() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(BackgroundFileHandleChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundFileHandleChild::AssertIsOnOwningThread() const {
|
|
|
|
static_cast<BackgroundMutableFileChild*>(Manager())->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
void BackgroundFileHandleChild::SendDeleteMeInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mFileHandle) {
|
|
|
|
NoteActorDestroyed();
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundFileHandleChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFileHandleChild::NoteActorDestroyed() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT_IF(mTemporaryStrongFileHandle, mFileHandle);
|
|
|
|
|
|
|
|
if (mFileHandle) {
|
|
|
|
mFileHandle->ClearBackgroundActor();
|
|
|
|
|
|
|
|
// Normally this would be DEBUG-only but NoteActorDestroyed is also called
|
2020-01-10 18:23:52 +03:00
|
|
|
// from SendDeleteMeInternal. In that case we're going to receive an
|
|
|
|
// actual ActorDestroy call later and we don't want to touch a dead
|
|
|
|
// object.
|
2017-06-07 13:36:42 +03:00
|
|
|
mTemporaryStrongFileHandle = nullptr;
|
|
|
|
mFileHandle = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFileHandleChild::NoteComplete() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT_IF(mFileHandle, mTemporaryStrongFileHandle);
|
|
|
|
|
|
|
|
mTemporaryStrongFileHandle = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFileHandleChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
NoteActorDestroyed();
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundFileHandleChild::RecvComplete(
|
2020-02-27 15:17:47 +03:00
|
|
|
const bool aAborted) {
|
2017-06-07 13:36:42 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mFileHandle);
|
|
|
|
|
|
|
|
mFileHandle->FireCompleteOrAbortEvents(aAborted);
|
|
|
|
|
|
|
|
NoteComplete();
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
|
|
|
PBackgroundFileRequestChild*
|
|
|
|
BackgroundFileHandleChild::AllocPBackgroundFileRequestChild(
|
|
|
|
const FileRequestParams& aParams) {
|
|
|
|
MOZ_CRASH(
|
|
|
|
"PBackgroundFileRequestChild actors should be manually "
|
|
|
|
"constructed!");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BackgroundFileHandleChild::DeallocPBackgroundFileRequestChild(
|
|
|
|
PBackgroundFileRequestChild* aActor) {
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
|
|
|
|
delete static_cast<BackgroundFileRequestChild*>(aActor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundFileRequestChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundFileRequestChild::BackgroundFileRequestChild(
|
|
|
|
IDBFileRequest* aFileRequest)
|
|
|
|
: mFileRequest(aFileRequest),
|
|
|
|
mFileHandle(aFileRequest->GetFileHandle()),
|
|
|
|
mActorDestroyed(false) {
|
|
|
|
MOZ_ASSERT(aFileRequest);
|
|
|
|
aFileRequest->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mFileHandle);
|
|
|
|
mFileHandle->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(BackgroundFileRequestChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundFileRequestChild::~BackgroundFileRequestChild() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!mFileHandle);
|
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(BackgroundFileRequestChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void BackgroundFileRequestChild::AssertIsOnOwningThread() const {
|
|
|
|
MOZ_ASSERT(mFileRequest);
|
|
|
|
mFileRequest->AssertIsOnOwningThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
void BackgroundFileRequestChild::HandleResponse(nsresult aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(NS_FAILED(aResponse));
|
|
|
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_FILEHANDLE);
|
|
|
|
MOZ_ASSERT(mFileHandle);
|
|
|
|
|
|
|
|
DispatchFileHandleErrorEvent(mFileRequest, aResponse, mFileHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFileRequestChild::HandleResponse(const nsCString& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
SetFileHandleResultAndDispatchSuccessEvent(mFileRequest, mFileHandle,
|
|
|
|
&aResponse);
|
2017-06-07 13:36:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFileRequestChild::HandleResponse(
|
|
|
|
const FileRequestMetadata& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
SetFileHandleResultAndDispatchSuccessEvent(mFileRequest, mFileHandle,
|
|
|
|
&aResponse);
|
2017-06-07 13:36:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFileRequestChild::HandleResponse(
|
2020-05-14 12:42:16 +03:00
|
|
|
const JS::Handle<JS::Value> aResponse) {
|
2017-06-07 13:36:42 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2020-05-14 12:42:33 +03:00
|
|
|
SetFileHandleResultAndDispatchSuccessEvent(mFileRequest, mFileHandle,
|
|
|
|
&aResponse);
|
2017-06-07 13:36:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundFileRequestChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_ASSERT(!mActorDestroyed);
|
|
|
|
|
|
|
|
mActorDestroyed = true;
|
|
|
|
|
|
|
|
if (mFileHandle) {
|
|
|
|
mFileHandle->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */
|
|
|
|
aWhy == Deletion);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
mFileHandle = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundFileRequestChild::Recv__delete__(
|
|
|
|
const FileRequestResponse& aResponse) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mFileRequest);
|
|
|
|
MOZ_ASSERT(mFileHandle);
|
|
|
|
|
|
|
|
if (mFileHandle->IsAborted()) {
|
|
|
|
// Always handle an "error" with ABORT_ERR if the file handle was aborted,
|
|
|
|
// even if the request succeeded or failed with another error.
|
|
|
|
HandleResponse(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
|
|
|
|
} else {
|
|
|
|
switch (aResponse.type()) {
|
|
|
|
case FileRequestResponse::Tnsresult:
|
|
|
|
HandleResponse(aResponse.get_nsresult());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FileRequestResponse::TFileRequestReadResponse:
|
|
|
|
HandleResponse(aResponse.get_FileRequestReadResponse().data());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FileRequestResponse::TFileRequestWriteResponse:
|
|
|
|
case FileRequestResponse::TFileRequestTruncateResponse:
|
|
|
|
case FileRequestResponse::TFileRequestFlushResponse:
|
|
|
|
HandleResponse(JS::UndefinedHandleValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FileRequestResponse::TFileRequestGetMetadataResponse:
|
|
|
|
HandleResponse(
|
|
|
|
aResponse.get_FileRequestGetMetadataResponse().metadata());
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2022-03-03 11:33:15 +03:00
|
|
|
return IPC_FAIL(this, "Unknown response type!");
|
2017-06-07 13:36:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */ true);
|
|
|
|
|
|
|
|
// Null this out so that we don't try to call OnRequestFinished() again in
|
|
|
|
// ActorDestroy.
|
|
|
|
mFileHandle = nullptr;
|
|
|
|
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult BackgroundFileRequestChild::RecvProgress(
|
2020-02-27 15:17:47 +03:00
|
|
|
const uint64_t aProgress, const uint64_t aProgressMax) {
|
2017-06-07 13:36:42 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mFileRequest);
|
|
|
|
|
|
|
|
mFileRequest->FireProgressEvent(aProgress, aProgressMax);
|
|
|
|
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2015-11-22 12:44:33 +03:00
|
|
|
/*******************************************************************************
|
|
|
|
* BackgroundUtilsChild
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
BackgroundUtilsChild::BackgroundUtilsChild(IndexedDatabaseManager* aManager)
|
|
|
|
: mManager(aManager) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aManager);
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(indexedDB::BackgroundUtilsChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
BackgroundUtilsChild::~BackgroundUtilsChild() {
|
|
|
|
MOZ_COUNT_DTOR(indexedDB::BackgroundUtilsChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundUtilsChild::SendDeleteMeInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mManager) {
|
|
|
|
mManager->ClearBackgroundActor();
|
|
|
|
mManager = nullptr;
|
|
|
|
|
|
|
|
MOZ_ALWAYS_TRUE(PBackgroundIndexedDBUtilsChild::SendDeleteMe());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BackgroundUtilsChild::ActorDestroy(ActorDestroyReason aWhy) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mManager) {
|
|
|
|
mManager->ClearBackgroundActor();
|
|
|
|
#ifdef DEBUG
|
|
|
|
mManager = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-04 20:04:01 +03:00
|
|
|
} // namespace dom::indexedDB
|
2014-09-27 03:21:57 +04:00
|
|
|
} // namespace mozilla
|