Bug 1855142 - Ensure IndexedDabaseManager::mLocale separately; r=dom-storage-reviewers,jari

mLocale is currently initialized in IndexedDatabaseManager::Init which is
called from IndexedDatabaseManager::GetOrCreate if the manager doesn't exist.
This can be a problem when IndexedDatabaseManager::GetOrCreate is called very
early,for example in nsLayoutStatics::Initialize in the parent process.

This is a preparation for moving IndexedDatabaseManager::GetOrCreate from
FactoryOp::Open to InitializeQuotaManager.

Differential Revision: https://phabricator.services.mozilla.com/D189891
This commit is contained in:
Jan Varga 2024-02-29 15:28:47 +00:00
Родитель c99f1c4777
Коммит 67a8ed7ac0
11 изменённых файлов: 106 добавлений и 49 удалений

Просмотреть файл

@ -2092,6 +2092,7 @@ class TransactionDatabaseOperationBase : public DatabaseOperationBase {
class Factory final : public PBackgroundIDBFactoryParent, class Factory final : public PBackgroundIDBFactoryParent,
public AtomicSafeRefCounted<Factory> { public AtomicSafeRefCounted<Factory> {
nsCString mSystemLocale;
RefPtr<DatabaseLoggingInfo> mLoggingInfo; RefPtr<DatabaseLoggingInfo> mLoggingInfo;
#ifdef DEBUG #ifdef DEBUG
@ -2103,7 +2104,7 @@ class Factory final : public PBackgroundIDBFactoryParent,
public: public:
[[nodiscard]] static SafeRefPtr<Factory> Create( [[nodiscard]] static SafeRefPtr<Factory> Create(
const LoggingInfo& aLoggingInfo); const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale);
DatabaseLoggingInfo* GetLoggingInfo() const { DatabaseLoggingInfo* GetLoggingInfo() const {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
@ -2112,11 +2113,14 @@ class Factory final : public PBackgroundIDBFactoryParent,
return mLoggingInfo; return mLoggingInfo;
} }
const nsCString& GetSystemLocale() const { return mSystemLocale; }
MOZ_DECLARE_REFCOUNTED_TYPENAME(mozilla::dom::indexedDB::Factory) MOZ_DECLARE_REFCOUNTED_TYPENAME(mozilla::dom::indexedDB::Factory)
MOZ_INLINE_DECL_SAFEREFCOUNTING_INHERITED(Factory, AtomicSafeRefCounted) MOZ_INLINE_DECL_SAFEREFCOUNTING_INHERITED(Factory, AtomicSafeRefCounted)
// Only constructed in Create(). // Only constructed in Create().
explicit Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo); Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo,
const nsACString& aSystemLocale);
// IPDL methods are only called by IPDL. // IPDL methods are only called by IPDL.
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;
@ -6545,7 +6549,7 @@ already_AddRefed<nsIThreadPool> MakeConnectionIOTarget() {
******************************************************************************/ ******************************************************************************/
already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent( already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent(
const LoggingInfo& aLoggingInfo) { const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread())) { if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread())) {
@ -6559,15 +6563,15 @@ already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent(
return nullptr; return nullptr;
} }
SafeRefPtr<Factory> actor = Factory::Create(aLoggingInfo); SafeRefPtr<Factory> actor = Factory::Create(aLoggingInfo, aSystemLocale);
MOZ_ASSERT(actor); MOZ_ASSERT(actor);
return actor.forget(); return actor.forget();
} }
bool RecvPBackgroundIDBFactoryConstructor( bool RecvPBackgroundIDBFactoryConstructor(
PBackgroundIDBFactoryParent* aActor, PBackgroundIDBFactoryParent* aActor, const LoggingInfo& /* aLoggingInfo */,
const LoggingInfo& /* aLoggingInfo */) { const nsACString& /* aSystemLocale */) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor); MOZ_ASSERT(aActor);
MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread()); MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread());
@ -8976,8 +8980,10 @@ DatabaseLoggingInfo::~DatabaseLoggingInfo() {
* Factory * Factory
******************************************************************************/ ******************************************************************************/
Factory::Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo) Factory::Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo,
: mLoggingInfo(std::move(aLoggingInfo)) const nsACString& aSystemLocale)
: mSystemLocale(aSystemLocale),
mLoggingInfo(std::move(aLoggingInfo))
#ifdef DEBUG #ifdef DEBUG
, ,
mActorDestroyed(false) mActorDestroyed(false)
@ -8990,7 +8996,8 @@ Factory::Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo)
Factory::~Factory() { MOZ_ASSERT(mActorDestroyed); } Factory::~Factory() { MOZ_ASSERT(mActorDestroyed); }
// static // static
SafeRefPtr<Factory> Factory::Create(const LoggingInfo& aLoggingInfo) { SafeRefPtr<Factory> Factory::Create(const LoggingInfo& aLoggingInfo,
const nsACString& aSystemLocale) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread()); MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread());
@ -9027,7 +9034,7 @@ SafeRefPtr<Factory> Factory::Create(const LoggingInfo& aLoggingInfo) {
return do_AddRef(entry.Data()); return do_AddRef(entry.Data());
}); });
return MakeSafeRefPtr<Factory>(std::move(loggingInfo)); return MakeSafeRefPtr<Factory>(std::move(loggingInfo), aSystemLocale);
} }
void Factory::ActorDestroy(ActorDestroyReason aWhy) { void Factory::ActorDestroy(ActorDestroyReason aWhy) {
@ -15348,7 +15355,7 @@ nsresult OpenDatabaseOp::LoadDatabaseInformation(
QM_TRY_INSPECT( QM_TRY_INSPECT(
const auto& lastIndexId, const auto& lastIndexId,
([&aConnection, ([this, &aConnection,
&objectStores]() -> mozilla::Result<IndexOrObjectStoreId, nsresult> { &objectStores]() -> mozilla::Result<IndexOrObjectStoreId, nsresult> {
// Load index information // Load index information
QM_TRY_INSPECT( QM_TRY_INSPECT(
@ -15365,7 +15372,7 @@ nsresult OpenDatabaseOp::LoadDatabaseInformation(
QM_TRY(CollectWhileHasResult( QM_TRY(CollectWhileHasResult(
*stmt, *stmt,
[&lastIndexId, &objectStores, &aConnection, [this, &lastIndexId, &objectStores, &aConnection,
usedIds = Maybe<nsTHashSet<uint64_t>>{}, usedIds = Maybe<nsTHashSet<uint64_t>>{},
usedNames = Maybe<nsTHashSet<nsString>>{}]( usedNames = Maybe<nsTHashSet<nsString>>{}](
auto& stmt) mutable -> mozilla::Result<Ok, nsresult> { auto& stmt) mutable -> mozilla::Result<Ok, nsresult> {
@ -15456,8 +15463,7 @@ nsresult OpenDatabaseOp::LoadDatabaseInformation(
indexMetadata->mCommonMetadata.locale(); indexMetadata->mCommonMetadata.locale();
const bool& isAutoLocale = const bool& isAutoLocale =
indexMetadata->mCommonMetadata.autoLocale(); indexMetadata->mCommonMetadata.autoLocale();
const nsCString& systemLocale = const nsCString& systemLocale = mFactory->GetSystemLocale();
IndexedDatabaseManager::GetLocale();
if (!systemLocale.IsEmpty() && isAutoLocale && if (!systemLocale.IsEmpty() && isAutoLocale &&
!indexedLocale.Equals(systemLocale)) { !indexedLocale.Equals(systemLocale)) {
QM_TRY(MOZ_TO_RESULT(UpdateLocaleAwareIndex( QM_TRY(MOZ_TO_RESULT(UpdateLocaleAwareIndex(

Просмотреть файл

@ -38,10 +38,11 @@ class PBackgroundIDBFactoryParent;
class PBackgroundIndexedDBUtilsParent; class PBackgroundIndexedDBUtilsParent;
already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent( already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent(
const LoggingInfo& aLoggingInfo); const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale);
bool RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor, bool RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor,
const LoggingInfo& aLoggingInfo); const LoggingInfo& aLoggingInfo,
const nsACString& aSystemLocale);
bool DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor); bool DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor);

Просмотреть файл

@ -242,6 +242,12 @@ Result<RefPtr<IDBFactory>, nsresult> IDBFactory::CreateForMainThreadJSInternal(
return Err(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return Err(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
} }
nsresult rv = mgr->EnsureLocale();
if (NS_WARN_IF(NS_FAILED(rv))) {
IDB_REPORT_INTERNAL_ERR();
return Err(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
};
return CreateInternal(aGlobal, std::move(aPrincipalInfo), return CreateInternal(aGlobal, std::move(aPrincipalInfo),
/* aInnerWindowID */ 0); /* aInnerWindowID */ 0);
} }
@ -283,10 +289,17 @@ nsresult IDBFactory::AllowedForWindowInternal(
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow); MOZ_ASSERT(aWindow);
if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) { IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate();
if (NS_WARN_IF(!mgr)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
nsresult rv = mgr->EnsureLocale();
if (NS_WARN_IF(NS_FAILED(rv))) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
};
StorageAccess access = StorageAllowedForWindow(aWindow); StorageAccess access = StorageAllowedForWindow(aWindow);
// the factory callsite records whether the browser is in private browsing. // the factory callsite records whether the browser is in private browsing.
@ -341,10 +354,16 @@ bool IDBFactory::AllowedForPrincipal(nsIPrincipal* aPrincipal,
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aPrincipal);
if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) { IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate();
if (NS_WARN_IF(!mgr)) {
return false; return false;
} }
nsresult rv = mgr->EnsureLocale();
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
};
if (aPrincipal->IsSystemPrincipal()) { if (aPrincipal->IsSystemPrincipal()) {
if (aIsSystemPrincipal) { if (aIsSystemPrincipal) {
*aIsSystemPrincipal = true; *aIsSystemPrincipal = true;
@ -641,7 +660,8 @@ RefPtr<IDBOpenDBRequest> IDBFactory::OpenInternal(
mBackgroundActor = static_cast<BackgroundFactoryChild*>( mBackgroundActor = static_cast<BackgroundFactoryChild*>(
backgroundActor->SendPBackgroundIDBFactoryConstructor( backgroundActor->SendPBackgroundIDBFactoryConstructor(
actor, idbThreadLocal->GetLoggingInfo())); actor, idbThreadLocal->GetLoggingInfo(),
IndexedDatabaseManager::GetLocale()));
if (NS_WARN_IF(!mBackgroundActor)) { if (NS_WARN_IF(!mBackgroundActor)) {
mBackgroundActorFailed = true; mBackgroundActorFailed = true;

Просмотреть файл

@ -296,25 +296,6 @@ nsresult IndexedDatabaseManager::Init() {
Preferences::RegisterCallbackAndCall(MaxPreloadExtraRecordsPrefChangeCallback, Preferences::RegisterCallbackAndCall(MaxPreloadExtraRecordsPrefChangeCallback,
kPrefMaxPreloadExtraRecords); kPrefMaxPreloadExtraRecords);
nsAutoCString acceptLang;
Preferences::GetLocalizedCString("intl.accept_languages", acceptLang);
// Split values on commas.
for (const auto& lang :
nsCCharSeparatedTokenizer(acceptLang, ',').ToRange()) {
mozilla::intl::LocaleCanonicalizer::Vector asciiString{};
auto result = mozilla::intl::LocaleCanonicalizer::CanonicalizeICULevel1(
PromiseFlatCString(lang).get(), asciiString);
if (result.isOk()) {
mLocale.AssignASCII(asciiString);
break;
}
}
if (mLocale.IsEmpty()) {
mLocale.AssignLiteral("en_US");
}
return NS_OK; return NS_OK;
} }
@ -652,11 +633,37 @@ void IndexedDatabaseManager::LoggingModePrefChangedCallback(
} }
} }
nsresult IndexedDatabaseManager::EnsureLocale() {
MOZ_ASSERT(NS_IsMainThread());
nsAutoCString acceptLang;
Preferences::GetLocalizedCString("intl.accept_languages", acceptLang);
// Split values on commas.
for (const auto& lang :
nsCCharSeparatedTokenizer(acceptLang, ',').ToRange()) {
mozilla::intl::LocaleCanonicalizer::Vector asciiString{};
auto result = mozilla::intl::LocaleCanonicalizer::CanonicalizeICULevel1(
PromiseFlatCString(lang).get(), asciiString);
if (result.isOk()) {
mLocale.AssignASCII(asciiString);
break;
}
}
if (mLocale.IsEmpty()) {
mLocale.AssignLiteral("en_US");
}
return NS_OK;
}
// static // static
const nsCString& IndexedDatabaseManager::GetLocale() { const nsCString& IndexedDatabaseManager::GetLocale() {
IndexedDatabaseManager* idbManager = Get(); IndexedDatabaseManager* idbManager = Get();
MOZ_ASSERT(idbManager, "IDBManager is not ready!"); MOZ_ASSERT(idbManager, "IDBManager is not ready!");
MOZ_ASSERT(!idbManager->mLocale.IsEmpty());
return idbManager->mLocale; return idbManager->mLocale;
} }

Просмотреть файл

@ -123,6 +123,9 @@ class IndexedDatabaseManager final {
nsresult FlushPendingFileDeletions(); nsresult FlushPendingFileDeletions();
// XXX This extra explicit initialization should go away with bug 1730706.
nsresult EnsureLocale();
static const nsCString& GetLocale(); static const nsCString& GetLocale();
static bool ResolveSandboxBinding(JSContext* aCx); static bool ResolveSandboxBinding(JSContext* aCx);

Просмотреть файл

@ -1419,10 +1419,16 @@ nsresult RuntimeService::Init() {
Preferences::GetInt(PREF_WORKERS_MAX_PER_DOMAIN, MAX_WORKERS_PER_DOMAIN); Preferences::GetInt(PREF_WORKERS_MAX_PER_DOMAIN, MAX_WORKERS_PER_DOMAIN);
gMaxWorkersPerDomain = std::max(0, maxPerDomain); gMaxWorkersPerDomain = std::max(0, maxPerDomain);
if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) { IndexedDatabaseManager* idm = IndexedDatabaseManager::GetOrCreate();
if (NS_WARN_IF(!idm)) {
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
rv = idm->EnsureLocale();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// PerformanceService must be initialized on the main-thread. // PerformanceService must be initialized on the main-thread.
PerformanceService::GetOrCreate(); PerformanceService::GetOrCreate();

Просмотреть файл

@ -2804,7 +2804,12 @@ nsresult WorkerPrivate::GetLoadInfo(
AssertIsOnMainThread(); AssertIsOnMainThread();
// Make sure that the IndexedDatabaseManager is set up // Make sure that the IndexedDatabaseManager is set up
Unused << NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate()); IndexedDatabaseManager* idm = IndexedDatabaseManager::GetOrCreate();
if (idm) {
Unused << NS_WARN_IF(NS_FAILED(idm->EnsureLocale()));
} else {
NS_WARNING("Failed to get IndexedDatabaseManager!");
}
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
MOZ_ASSERT(ssm); MOZ_ASSERT(ssm);

Просмотреть файл

@ -232,7 +232,12 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) {
// Ensure that the IndexedDatabaseManager is initialized so that if any // Ensure that the IndexedDatabaseManager is initialized so that if any
// workers do any IndexedDB calls that all of IDB's prefs/etc. are // workers do any IndexedDB calls that all of IDB's prefs/etc. are
// initialized. // initialized.
Unused << NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate()); IndexedDatabaseManager* idm = IndexedDatabaseManager::GetOrCreate();
if (idm) {
Unused << NS_WARN_IF(NS_FAILED(idm->EnsureLocale()));
} else {
NS_WARNING("Failed to get IndexedDatabaseManager!");
}
auto scopeExit = auto scopeExit =
MakeScopeExit([&] { ExceptionalErrorTransitionDuringExecWorker(); }); MakeScopeExit([&] { ExceptionalErrorTransitionDuringExecWorker(); });

Просмотреть файл

@ -191,26 +191,28 @@ bool BackgroundParentImpl::DeallocPBackgroundTestParent(
} }
auto BackgroundParentImpl::AllocPBackgroundIDBFactoryParent( auto BackgroundParentImpl::AllocPBackgroundIDBFactoryParent(
const LoggingInfo& aLoggingInfo) const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale)
-> already_AddRefed<PBackgroundIDBFactoryParent> { -> already_AddRefed<PBackgroundIDBFactoryParent> {
using mozilla::dom::indexedDB::AllocPBackgroundIDBFactoryParent; using mozilla::dom::indexedDB::AllocPBackgroundIDBFactoryParent;
AssertIsInMainProcess(); AssertIsInMainProcess();
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
return AllocPBackgroundIDBFactoryParent(aLoggingInfo); return AllocPBackgroundIDBFactoryParent(aLoggingInfo, aSystemLocale);
} }
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor( BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor(
PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo) { PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo,
const nsACString& aSystemLocale) {
using mozilla::dom::indexedDB::RecvPBackgroundIDBFactoryConstructor; using mozilla::dom::indexedDB::RecvPBackgroundIDBFactoryConstructor;
AssertIsInMainProcess(); AssertIsInMainProcess();
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor); MOZ_ASSERT(aActor);
if (!RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo)) { if (!RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo,
aSystemLocale)) {
return IPC_FAIL_NO_REASON(this); return IPC_FAIL_NO_REASON(this);
} }
return IPC_OK(); return IPC_OK();

Просмотреть файл

@ -31,11 +31,12 @@ class BackgroundParentImpl : public PBackgroundParent {
bool DeallocPBackgroundTestParent(PBackgroundTestParent* aActor) override; bool DeallocPBackgroundTestParent(PBackgroundTestParent* aActor) override;
already_AddRefed<PBackgroundIDBFactoryParent> already_AddRefed<PBackgroundIDBFactoryParent>
AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo) override; AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo,
const nsACString& aSystemLocale) override;
mozilla::ipc::IPCResult RecvPBackgroundIDBFactoryConstructor( mozilla::ipc::IPCResult RecvPBackgroundIDBFactoryConstructor(
PBackgroundIDBFactoryParent* aActor, PBackgroundIDBFactoryParent* aActor, const LoggingInfo& aLoggingInfo,
const LoggingInfo& aLoggingInfo) override; const nsACString& aSystemLocale) override;
PBackgroundIndexedDBUtilsParent* AllocPBackgroundIndexedDBUtilsParent() PBackgroundIndexedDBUtilsParent* AllocPBackgroundIndexedDBUtilsParent()
override; override;

Просмотреть файл

@ -129,7 +129,8 @@ parent:
// Only called at startup during mochitests to check the basic infrastructure. // Only called at startup during mochitests to check the basic infrastructure.
async PBackgroundTest(nsCString testArg); async PBackgroundTest(nsCString testArg);
async PBackgroundIDBFactory(LoggingInfo loggingInfo); async PBackgroundIDBFactory(LoggingInfo loggingInfo,
nsCString systemLocale);
async PBackgroundIndexedDBUtils(); async PBackgroundIndexedDBUtils();