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

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

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

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

@ -242,6 +242,12 @@ Result<RefPtr<IDBFactory>, nsresult> IDBFactory::CreateForMainThreadJSInternal(
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),
/* aInnerWindowID */ 0);
}
@ -283,10 +289,17 @@ nsresult IDBFactory::AllowedForWindowInternal(
MOZ_ASSERT(NS_IsMainThread());
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;
}
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);
// 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(aPrincipal);
if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) {
IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate();
if (NS_WARN_IF(!mgr)) {
return false;
}
nsresult rv = mgr->EnsureLocale();
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
};
if (aPrincipal->IsSystemPrincipal()) {
if (aIsSystemPrincipal) {
*aIsSystemPrincipal = true;
@ -641,7 +660,8 @@ RefPtr<IDBOpenDBRequest> IDBFactory::OpenInternal(
mBackgroundActor = static_cast<BackgroundFactoryChild*>(
backgroundActor->SendPBackgroundIDBFactoryConstructor(
actor, idbThreadLocal->GetLoggingInfo()));
actor, idbThreadLocal->GetLoggingInfo(),
IndexedDatabaseManager::GetLocale()));
if (NS_WARN_IF(!mBackgroundActor)) {
mBackgroundActorFailed = true;

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

@ -296,25 +296,6 @@ nsresult IndexedDatabaseManager::Init() {
Preferences::RegisterCallbackAndCall(MaxPreloadExtraRecordsPrefChangeCallback,
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;
}
@ -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
const nsCString& IndexedDatabaseManager::GetLocale() {
IndexedDatabaseManager* idbManager = Get();
MOZ_ASSERT(idbManager, "IDBManager is not ready!");
MOZ_ASSERT(!idbManager->mLocale.IsEmpty());
return idbManager->mLocale;
}

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

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

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

@ -1419,10 +1419,16 @@ nsresult RuntimeService::Init() {
Preferences::GetInt(PREF_WORKERS_MAX_PER_DOMAIN, MAX_WORKERS_PER_DOMAIN);
gMaxWorkersPerDomain = std::max(0, maxPerDomain);
if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) {
IndexedDatabaseManager* idm = IndexedDatabaseManager::GetOrCreate();
if (NS_WARN_IF(!idm)) {
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::GetOrCreate();

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

@ -2804,7 +2804,12 @@ nsresult WorkerPrivate::GetLoadInfo(
AssertIsOnMainThread();
// 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();
MOZ_ASSERT(ssm);

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

@ -232,7 +232,12 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) {
// Ensure that the IndexedDatabaseManager is initialized so that if any
// workers do any IndexedDB calls that all of IDB's prefs/etc. are
// 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 =
MakeScopeExit([&] { ExceptionalErrorTransitionDuringExecWorker(); });

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

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

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

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

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

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