/* -*- 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, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ProfilerHelpers.h" #include "BackgroundChildImpl.h" #include "GeckoProfiler.h" #include "IDBDatabase.h" #include "IDBIndex.h" #include "IDBKeyRange.h" #include "IDBObjectStore.h" #include "IDBTransaction.h" #include "Key.h" #include "ThreadLocal.h" #include "mozilla/dom/Event.h" #include "nsReadableUtils.h" namespace mozilla::dom::indexedDB { namespace { static const char kQuote = '\"'; static const char kOpenBracket = '['; static const char kCloseBracket = ']'; static const char kOpenParen = '('; static const char kCloseParen = ')'; void LoggingHelper(bool aUseProfiler, const char* aFmt, va_list args) { MOZ_ASSERT(IndexedDatabaseManager::GetLoggingMode() != IndexedDatabaseManager::Logging_Disabled); MOZ_ASSERT(aFmt); mozilla::LogModule* logModule = IndexedDatabaseManager::GetLoggingModule(); MOZ_ASSERT(logModule); static const mozilla::LogLevel logLevel = LogLevel::Warning; if (MOZ_LOG_TEST(logModule, logLevel) || (aUseProfiler && profiler_thread_is_being_profiled())) { nsAutoCString message; message.AppendVprintf(aFmt, args); MOZ_LOG(logModule, logLevel, ("%s", message.get())); if (aUseProfiler) { PROFILER_MARKER_UNTYPED(message, DOM); } } } } // namespace template LoggingIdString::LoggingIdString() { using mozilla::ipc::BackgroundChildImpl; if (!CheckLoggingMode || IndexedDatabaseManager::GetLoggingMode() != IndexedDatabaseManager::Logging_Disabled) { const BackgroundChildImpl::ThreadLocal* threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread(); if (threadLocal) { const auto& idbThreadLocal = threadLocal->mIndexedDBThreadLocal; if (idbThreadLocal) { Assign(idbThreadLocal->IdString()); } } } } template LoggingIdString::LoggingIdString(const nsID& aID) { static_assert(NSID_LENGTH > 1, "NSID_LENGTH is set incorrectly!"); static_assert(NSID_LENGTH <= kStorageSize, "nsID string won't fit in our storage!"); // Capacity() excludes the null terminator; NSID_LENGTH includes it. MOZ_ASSERT(Capacity() + 1 == NSID_LENGTH); if (!CheckLoggingMode || IndexedDatabaseManager::GetLoggingMode() != IndexedDatabaseManager::Logging_Disabled) { // NSID_LENGTH counts the null terminator, SetLength() does not. SetLength(NSID_LENGTH - 1); aID.ToProvidedString( *reinterpret_cast(BeginWriting())); } } template class LoggingIdString; template class LoggingIdString; LoggingString::LoggingString(IDBDatabase* aDatabase) : nsAutoCString(kQuote) { MOZ_ASSERT(aDatabase); AppendUTF16toUTF8(aDatabase->Name(), *this); Append(kQuote); } LoggingString::LoggingString(const IDBTransaction& aTransaction) : nsAutoCString(kOpenBracket) { constexpr auto kCommaSpace = ", "_ns; StringJoinAppend(*this, kCommaSpace, aTransaction.ObjectStoreNamesInternal(), [](nsACString& dest, const auto& store) { dest.Append(kQuote); AppendUTF16toUTF8(store, dest); dest.Append(kQuote); }); Append(kCloseBracket); Append(kCommaSpace); switch (aTransaction.GetMode()) { case IDBTransaction::Mode::ReadOnly: AppendLiteral("\"readonly\""); break; case IDBTransaction::Mode::ReadWrite: AppendLiteral("\"readwrite\""); break; case IDBTransaction::Mode::ReadWriteFlush: AppendLiteral("\"readwriteflush\""); break; case IDBTransaction::Mode::Cleanup: AppendLiteral("\"cleanup\""); break; case IDBTransaction::Mode::VersionChange: AppendLiteral("\"versionchange\""); break; default: MOZ_CRASH("Unknown mode!"); }; } LoggingString::LoggingString(IDBObjectStore* aObjectStore) : nsAutoCString(kQuote) { MOZ_ASSERT(aObjectStore); AppendUTF16toUTF8(aObjectStore->Name(), *this); Append(kQuote); } LoggingString::LoggingString(IDBIndex* aIndex) : nsAutoCString(kQuote) { MOZ_ASSERT(aIndex); AppendUTF16toUTF8(aIndex->Name(), *this); Append(kQuote); } LoggingString::LoggingString(IDBKeyRange* aKeyRange) { if (aKeyRange) { if (aKeyRange->IsOnly()) { Assign(LoggingString(aKeyRange->Lower())); } else { if (aKeyRange->LowerOpen()) { Assign(kOpenParen); } else { Assign(kOpenBracket); } Append(LoggingString(aKeyRange->Lower())); AppendLiteral(", "); Append(LoggingString(aKeyRange->Upper())); if (aKeyRange->UpperOpen()) { Append(kCloseParen); } else { Append(kCloseBracket); } } } else { AssignLiteral(""); } } LoggingString::LoggingString(const Key& aKey) { if (aKey.IsUnset()) { AssignLiteral(""); } else if (aKey.IsFloat()) { AppendPrintf("%g", aKey.ToFloat()); } else if (aKey.IsDate()) { AppendPrintf("", aKey.ToDateMsec()); } else if (aKey.IsString()) { AppendPrintf("\"%s\"", NS_ConvertUTF16toUTF8(aKey.ToString()).get()); } else if (aKey.IsBinary()) { AssignLiteral("[object ArrayBuffer]"); } else { MOZ_ASSERT(aKey.IsArray()); AssignLiteral("[...]"); } } LoggingString::LoggingString(const IDBCursorDirection aDirection) { switch (aDirection) { case IDBCursorDirection::Next: AssignLiteral("\"next\""); break; case IDBCursorDirection::Nextunique: AssignLiteral("\"nextunique\""); break; case IDBCursorDirection::Prev: AssignLiteral("\"prev\""); break; case IDBCursorDirection::Prevunique: AssignLiteral("\"prevunique\""); break; default: MOZ_CRASH("Unknown direction!"); }; } LoggingString::LoggingString(const Optional& aVersion) { if (aVersion.WasPassed()) { AppendInt(aVersion.Value()); } else { AssignLiteral(""); } } LoggingString::LoggingString(const Optional& aLimit) { if (aLimit.WasPassed()) { AppendInt(aLimit.Value()); } else { AssignLiteral(""); } } LoggingString::LoggingString(IDBObjectStore* aObjectStore, const Key& aKey) { MOZ_ASSERT(aObjectStore); if (!aObjectStore->HasValidKeyPath()) { Append(LoggingString(aKey)); } } LoggingString::LoggingString(Event* aEvent, const char16_t* aDefault) : nsAutoCString(kQuote) { MOZ_ASSERT(aDefault); nsAutoString eventType; if (aEvent) { aEvent->GetType(eventType); } else { eventType = nsDependentString(aDefault); } AppendUTF16toUTF8(eventType, *this); Append(kQuote); } void LoggingHelper(const char* aDetailedFmt, const char* aConciseFmt, ...) { const IndexedDatabaseManager::LoggingMode mode = IndexedDatabaseManager::GetLoggingMode(); if (mode != IndexedDatabaseManager::Logging_Disabled) { const char* fmt; if (mode == IndexedDatabaseManager::Logging_Concise || mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks) { fmt = aConciseFmt; } else { MOZ_ASSERT(mode == IndexedDatabaseManager::Logging_Detailed || mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks); fmt = aDetailedFmt; } const bool useProfiler = mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks || mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks; va_list args; va_start(args, aConciseFmt); LoggingHelper(useProfiler, fmt, args); va_end(args); } } } // namespace mozilla::dom::indexedDB