Source code
Revision control
Copy as Markdown
Other Tools
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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,
#include "mozilla/dom/quota/CachingDatabaseConnection.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/ipc/BackgroundParent.h"
namespace mozilla::dom::quota {
CachingDatabaseConnection::CachingDatabaseConnection(
MovingNotNull<nsCOMPtr<mozIStorageConnection>> aStorageConnection)
:
#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
mOwningEventTarget{nsAutoOwningEventTarget{}},
#endif
mStorageConnection(std::move(aStorageConnection)) {
}
void CachingDatabaseConnection::LazyInit(
MovingNotNull<nsCOMPtr<mozIStorageConnection>> aStorageConnection) {
#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
mOwningEventTarget.init();
#endif
mStorageConnection.init(std::move(aStorageConnection));
}
Result<CachingDatabaseConnection::CachedStatement, nsresult>
CachingDatabaseConnection::GetCachedStatement(const nsACString& aQuery) {
AssertIsOnConnectionThread();
MOZ_ASSERT(!aQuery.IsEmpty());
MOZ_ASSERT(mStorageConnection);
AUTO_PROFILER_LABEL("CachingDatabaseConnection::GetCachedStatement", DOM);
QM_TRY_UNWRAP(
auto stmt,
mCachedStatements.TryLookupOrInsertWith(
aQuery, [&]() -> Result<nsCOMPtr<mozIStorageStatement>, nsresult> {
const auto extraInfo = ScopedLogExtraInfo{
ScopedLogExtraInfo::kTagQueryTainted, aQuery};
QM_TRY_RETURN(
MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(
nsCOMPtr<mozIStorageStatement>, **mStorageConnection,
CreateStatement, aQuery),
QM_PROPAGATE,
([&aQuery,
&storageConnection = **mStorageConnection](const auto&) {
#ifdef DEBUG
nsCString msg;
MOZ_ALWAYS_SUCCEEDS(
storageConnection.GetLastErrorString(msg));
nsAutoCString error =
"The statement '"_ns + aQuery +
"' failed to compile with the error message '"_ns + msg +
"'."_ns;
NS_WARNING(error.get());
#else
(void)aQuery;
#endif
}));
}));
return CachedStatement{this, std::move(stmt), aQuery};
}
Result<CachingDatabaseConnection::BorrowedStatement, nsresult>
CachingDatabaseConnection::BorrowCachedStatement(const nsACString& aQuery) {
QM_TRY_UNWRAP(auto cachedStatement, GetCachedStatement(aQuery));
return cachedStatement.Borrow();
}
nsresult CachingDatabaseConnection::ExecuteCachedStatement(
const nsACString& aQuery) {
return ExecuteCachedStatement(
aQuery, [](auto&) -> Result<Ok, nsresult> { return Ok{}; });
}
void CachingDatabaseConnection::Close() {
AssertIsOnConnectionThread();
MOZ_ASSERT(HasStorageConnection());
AUTO_PROFILER_LABEL("CachingDatabaseConnection::Close", DOM);
mCachedStatements.Clear();
MOZ_ALWAYS_SUCCEEDS((*mStorageConnection)->Close());
mStorageConnection.destroy();
mClosed = true;
}
#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING)
CachingDatabaseConnection::CachedStatement::CachedStatement()
# ifdef DEBUG
: mDEBUGConnection(nullptr)
# endif
{
AssertIsOnConnectionThread();
MOZ_COUNT_CTOR(CachingDatabaseConnection::CachedStatement);
}
CachingDatabaseConnection::CachedStatement::~CachedStatement() {
AssertIsOnConnectionThread();
MOZ_COUNT_DTOR(CachingDatabaseConnection::CachedStatement);
}
#endif
CachingDatabaseConnection::CachedStatement::operator bool() const {
AssertIsOnConnectionThread();
return mStatement;
}
mozIStorageStatement& CachingDatabaseConnection::BorrowedStatement::operator*()
const {
return *operator->();
}
mozIStorageStatement* CachingDatabaseConnection::BorrowedStatement::operator->()
const {
MOZ_ASSERT(mStatement);
return mStatement;
}
CachingDatabaseConnection::BorrowedStatement
CachingDatabaseConnection::CachedStatement::Borrow() const {
AssertIsOnConnectionThread();
#ifdef QM_SCOPED_LOG_EXTRA_INFO_ENABLED
return BorrowedStatement{WrapNotNull(mStatement), mQuery};
#else
return BorrowedStatement{WrapNotNull(mStatement)};
#endif
}
CachingDatabaseConnection::CachedStatement::CachedStatement(
CachingDatabaseConnection* aConnection,
nsCOMPtr<mozIStorageStatement> aStatement, const nsACString& aQuery)
: mStatement(std::move(aStatement))
#ifdef QM_SCOPED_LOG_EXTRA_INFO_ENABLED
,
mQuery(aQuery)
#endif
#if defined(DEBUG)
,
mDEBUGConnection(aConnection)
#endif
{
#ifdef DEBUG
MOZ_ASSERT(aConnection);
aConnection->AssertIsOnConnectionThread();
#endif
MOZ_ASSERT(mStatement);
AssertIsOnConnectionThread();
MOZ_COUNT_CTOR(CachingDatabaseConnection::CachedStatement);
}
void CachingDatabaseConnection::CachedStatement::AssertIsOnConnectionThread()
const {
#ifdef DEBUG
if (mDEBUGConnection) {
mDEBUGConnection->AssertIsOnConnectionThread();
}
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mozilla::ipc::IsOnBackgroundThread());
#endif
}
Result<CachingDatabaseConnection::BorrowedStatement, nsresult>
CachingDatabaseConnection::LazyStatement::Borrow() {
if (!mCachedStatement) {
QM_TRY(Initialize());
}
return mCachedStatement.Borrow();
}
Result<Ok, nsresult> CachingDatabaseConnection::LazyStatement::Initialize() {
QM_TRY_UNWRAP(mCachedStatement, mConnection.GetCachedStatement(mQueryString));
return Ok{};
}
} // namespace mozilla::dom::quota