1507 lines
55 KiB
C++
1507 lines
55 KiB
C++
/* -*- 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 "ErrorList.h"
|
|
#include "IdentityCredentialStorageService.h"
|
|
#include "MainThreadUtils.h"
|
|
#include "mozilla/AppShutdown.h"
|
|
#include "mozilla/Base64.h"
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
#include "mozilla/dom/BindingDeclarations.h"
|
|
#include "mozilla/dom/IdentityCredential.h"
|
|
#include "mozilla/Components.h"
|
|
#include "mozilla/OriginAttributes.h"
|
|
#include "mozilla/Services.h"
|
|
#include "mozilla/StaticPrefs_dom.h"
|
|
#include "mozilla/StaticPtr.h"
|
|
#include "mozIStorageService.h"
|
|
#include "mozIStorageConnection.h"
|
|
#include "mozIStorageStatement.h"
|
|
#include "mozStorageCID.h"
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsCRT.h"
|
|
#include "nsDebug.h"
|
|
#include "nsDirectoryServiceUtils.h"
|
|
#include "nsIObserverService.h"
|
|
#include "nsIWritablePropertyBag2.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "nsVariant.h"
|
|
#include "prtime.h"
|
|
|
|
#define ACCOUNT_STATE_FILENAME "credentialstate.sqlite"_ns
|
|
#define SCHEMA_VERSION 2
|
|
#define MODIFIED_NOW PR_Now()
|
|
|
|
namespace mozilla {
|
|
|
|
StaticRefPtr<IdentityCredentialStorageService>
|
|
gIdentityCredentialStorageService;
|
|
|
|
NS_IMPL_ISUPPORTS(IdentityCredentialStorageService,
|
|
nsIIdentityCredentialStorageService, nsIObserver,
|
|
nsIAsyncShutdownBlocker)
|
|
|
|
already_AddRefed<IdentityCredentialStorageService>
|
|
IdentityCredentialStorageService::GetSingleton() {
|
|
AssertIsOnMainThread();
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
if (!gIdentityCredentialStorageService) {
|
|
gIdentityCredentialStorageService = new IdentityCredentialStorageService();
|
|
ClearOnShutdown(&gIdentityCredentialStorageService);
|
|
nsresult rv = gIdentityCredentialStorageService->Init();
|
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
|
}
|
|
RefPtr<IdentityCredentialStorageService> service =
|
|
gIdentityCredentialStorageService;
|
|
return service.forget();
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::GetName(nsAString& aName) {
|
|
aName = u"IdentityCredentialStorageService: Flushing data"_ns;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::BlockShutdown(
|
|
nsIAsyncShutdownClient* aClient) {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
nsresult rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
mShuttingDown.Flip();
|
|
|
|
if (mMemoryDatabaseConnection) {
|
|
Unused << mMemoryDatabaseConnection->Close();
|
|
mMemoryDatabaseConnection = nullptr;
|
|
}
|
|
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction(
|
|
"IdentityCredentialStorageService::BlockShutdown",
|
|
[self]() {
|
|
MonitorAutoLock lock(self->mMonitor);
|
|
|
|
MOZ_ASSERT(self->mPendingWrites == 0);
|
|
|
|
if (self->mDiskDatabaseConnection) {
|
|
Unused << self->mDiskDatabaseConnection->Close();
|
|
self->mDiskDatabaseConnection = nullptr;
|
|
}
|
|
|
|
self->mFinalized.Flip();
|
|
self->mMonitor.NotifyAll();
|
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
"IdentityCredentialStorageService::BlockShutdown "
|
|
"- mainthread callback",
|
|
[self]() { self->Finalize(); }));
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IdentityCredentialStorageService::GetState(nsIPropertyBag** aBagOut) {
|
|
return NS_OK;
|
|
}
|
|
|
|
already_AddRefed<nsIAsyncShutdownClient>
|
|
IdentityCredentialStorageService::GetAsyncShutdownBarrier() const {
|
|
nsresult rv;
|
|
nsCOMPtr<nsIAsyncShutdownService> svc = components::AsyncShutdown::Service();
|
|
MOZ_RELEASE_ASSERT(svc);
|
|
|
|
nsCOMPtr<nsIAsyncShutdownClient> client;
|
|
rv = svc->GetProfileBeforeChange(getter_AddRefs(client));
|
|
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
|
MOZ_RELEASE_ASSERT(client);
|
|
return client.forget();
|
|
}
|
|
|
|
nsresult IdentityCredentialStorageService::Init() {
|
|
AssertIsOnMainThread();
|
|
|
|
nsCOMPtr<nsIAsyncShutdownClient> asc = GetAsyncShutdownBarrier();
|
|
if (!asc) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
// We should only allow this service to start before its
|
|
// shutdown barrier is closed, so it never leaks.
|
|
bool closed;
|
|
nsresult rv = asc->GetIsClosed(&closed);
|
|
if (closed || NS_WARN_IF(NS_FAILED(rv))) {
|
|
MonitorAutoLock lock(mMonitor);
|
|
mShuttingDown.Flip();
|
|
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
|
|
}
|
|
|
|
rv = asc->AddBlocker(this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__,
|
|
u""_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
|
getter_AddRefs(mDatabaseFile));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = mDatabaseFile->AppendNative(ACCOUNT_STATE_FILENAME);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Register the PBMode cleaner (IdentityCredentialStorageService::Observe) as
|
|
// an observer.
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
mozilla::services::GetObserverService();
|
|
NS_ENSURE_TRUE(observerService, NS_ERROR_FAILURE);
|
|
observerService->AddObserver(this, "last-pb-context-exited", false);
|
|
|
|
rv = GetMemoryDatabaseConnection();
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
MonitorAutoLock lock(mMonitor);
|
|
mErrored.Flip();
|
|
return rv;
|
|
}
|
|
|
|
NS_ENSURE_SUCCESS(
|
|
NS_CreateBackgroundTaskQueue("IdentityCredentialStorage",
|
|
getter_AddRefs(mBackgroundThread)),
|
|
NS_ERROR_FAILURE);
|
|
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self]() {
|
|
MonitorAutoLock lock(self->mMonitor);
|
|
nsresult rv = self->GetDiskDatabaseConnection();
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
self->mErrored.Flip();
|
|
self->mMonitor.NotifyAll();
|
|
return;
|
|
}
|
|
|
|
rv = self->LoadMemoryTableFromDisk();
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
self->mErrored.Flip();
|
|
self->mMonitor.NotifyAll();
|
|
return;
|
|
}
|
|
|
|
self->mInitialized.Flip();
|
|
self->mMonitor.NotifyAll();
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult IdentityCredentialStorageService::WaitForInitialization() {
|
|
MOZ_ASSERT(NS_IsMainThread(),
|
|
"Must only wait for initialization in the main thread.");
|
|
MonitorAutoLock lock(mMonitor);
|
|
while (!mInitialized && !mErrored && !mShuttingDown) {
|
|
mMonitor.Wait();
|
|
}
|
|
if (mErrored) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
if (mShuttingDown) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void IdentityCredentialStorageService::Finalize() {
|
|
nsCOMPtr<nsIAsyncShutdownClient> asc = GetAsyncShutdownBarrier();
|
|
MOZ_ASSERT(asc);
|
|
DebugOnly<nsresult> rv = asc->RemoveBlocker(this);
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::ValidatePrincipal(
|
|
nsIPrincipal* aPrincipal) {
|
|
// We add some constraints on the RP principal where it is provided to reduce
|
|
// edge cases in implementation. These are reasonable constraints with the
|
|
// semantics of the store: it must be a http or https content principal.
|
|
NS_ENSURE_ARG_POINTER(aPrincipal);
|
|
NS_ENSURE_TRUE(aPrincipal->GetIsContentPrincipal(), NS_ERROR_FAILURE);
|
|
nsCString scheme;
|
|
nsresult rv = aPrincipal->GetScheme(scheme);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
NS_ENSURE_TRUE(scheme.Equals("http"_ns) || scheme.Equals("https"_ns),
|
|
NS_ERROR_FAILURE);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult IdentityCredentialStorageService::GetMemoryDatabaseConnection() {
|
|
return IdentityCredentialStorageService::GetDatabaseConnectionInternal(
|
|
getter_AddRefs(mMemoryDatabaseConnection), nullptr, false);
|
|
}
|
|
|
|
nsresult IdentityCredentialStorageService::GetDiskDatabaseConnection() {
|
|
NS_ENSURE_TRUE(mDatabaseFile, NS_ERROR_NULL_POINTER);
|
|
return IdentityCredentialStorageService::GetDatabaseConnectionInternal(
|
|
getter_AddRefs(mDiskDatabaseConnection), mDatabaseFile, true);
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::GetDatabaseConnectionInternal(
|
|
mozIStorageConnection** aDatabase, nsIFile* aFile, bool aRetry) {
|
|
NS_ENSURE_TRUE(aDatabase, NS_ERROR_UNEXPECTED);
|
|
NS_ENSURE_STATE(!(*aDatabase));
|
|
nsCOMPtr<mozIStorageService> storage =
|
|
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
|
|
NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED);
|
|
nsresult rv;
|
|
|
|
if (aFile) {
|
|
rv = storage->OpenDatabase(aFile, mozIStorageService::CONNECTION_DEFAULT,
|
|
aDatabase);
|
|
if (rv == NS_ERROR_FILE_CORRUPTED) {
|
|
rv = aFile->Remove(false);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = storage->OpenDatabase(aFile, mozIStorageService::CONNECTION_DEFAULT,
|
|
aDatabase);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
} else {
|
|
rv = storage->OpenSpecialDatabase(
|
|
kMozStorageMemoryStorageKey, "icsprivatedb"_ns,
|
|
mozIStorageService::CONNECTION_DEFAULT, aDatabase);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
NS_ENSURE_TRUE(*aDatabase, NS_ERROR_UNEXPECTED);
|
|
bool ready = false;
|
|
(*aDatabase)->GetConnectionReady(&ready);
|
|
if (!ready && aRetry) {
|
|
rv = aFile->Remove(false);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return IdentityCredentialStorageService::GetDatabaseConnectionInternal(
|
|
aDatabase, aFile, false);
|
|
} else {
|
|
NS_ENSURE_TRUE(ready, NS_ERROR_UNEXPECTED);
|
|
}
|
|
rv = EnsureTable(*aDatabase);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::EnsureTable(
|
|
mozIStorageConnection* aDatabase) {
|
|
NS_ENSURE_ARG_POINTER(aDatabase);
|
|
bool tableExists = false;
|
|
aDatabase->TableExists("identity"_ns, &tableExists);
|
|
if (!tableExists) {
|
|
// Currently there is only one schema version, so we just need to create the
|
|
// table. The definition uses no explicit rowid column, instead primary
|
|
// keying on the tuple defined in the spec. We store two bits and some
|
|
// additional data to make integration with the ClearDataService
|
|
// easier/possible.
|
|
nsresult rv = aDatabase->SetSchemaVersion(SCHEMA_VERSION);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aDatabase->ExecuteSimpleSQL(
|
|
"CREATE TABLE identity ("
|
|
"rpOrigin TEXT NOT NULL"
|
|
",idpOrigin TEXT NOT NULL"
|
|
",credentialId TEXT NOT NULL"
|
|
",registered INTEGER"
|
|
",allowLogout INTEGER"
|
|
",modificationTime INTEGER"
|
|
",rpBaseDomain TEXT"
|
|
",PRIMARY KEY (rpOrigin, idpOrigin, credentialId)"
|
|
")"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
tableExists = false;
|
|
aDatabase->TableExists("lightweight_identity"_ns, &tableExists);
|
|
if (!tableExists) {
|
|
// The definition uses no explicit rowid column, instead primary
|
|
// keying on the tuple defined in the spec.
|
|
nsresult rv = aDatabase->SetSchemaVersion(SCHEMA_VERSION);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aDatabase->ExecuteSimpleSQL(
|
|
"CREATE TABLE lightweight_identity ("
|
|
"idpOrigin TEXT NOT NULL"
|
|
",credentialId TEXT NOT NULL"
|
|
",name TEXT"
|
|
",iconDataURL TEXT"
|
|
",originAllowlist TEXT"
|
|
",dynamicAllowEndpoint TEXT"
|
|
",userDataExpireTime INTEGER"
|
|
",token TEXT"
|
|
",effectiveType TEXT"
|
|
",modificationTime INTEGER"
|
|
",idpBaseDomain TEXT"
|
|
",PRIMARY KEY (idpOrigin, credentialId)"
|
|
")"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
// Ensure the schema is up to date if the table already exists
|
|
int32_t schema;
|
|
nsresult rv = aDatabase->GetSchemaVersion(&schema);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
switch (schema) {
|
|
case 1:
|
|
rv = aDatabase->ExecuteSimpleSQL(
|
|
"ALTER TABLE lightweight_identity ADD COLUMN token TEXT;"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aDatabase->ExecuteSimpleSQL(
|
|
"ALTER TABLE lightweight_identity ADD COLUMN effectiveType TEXT;"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
[[fallthrough]];
|
|
default:
|
|
rv = aDatabase->SetSchemaVersion(SCHEMA_VERSION);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
IdentityCredentialStorageService::LoadLightweightMemoryTableFromDisk() {
|
|
MOZ_ASSERT(!NS_IsMainThread(),
|
|
"Must not load the table from disk in the main thread.");
|
|
auto constexpr selectAllQuery =
|
|
"SELECT idpOrigin, credentialId, name, iconDataURL, "
|
|
"originAllowlist, dynamicAllowEndpoint, userDataExpireTime,"
|
|
"token, effectiveType,"
|
|
"modificationTime, idpBaseDomain FROM lightweight_identity;"_ns;
|
|
auto constexpr insertQuery =
|
|
"INSERT INTO lightweight_identity(idpOrigin, credentialId, "
|
|
"name, iconDataURL, originAllowlist, dynamicAllowEndpoint, "
|
|
"userDataExpireTime, token, effectiveType,"
|
|
"modificationTime, idpBaseDomain) VALUES (:idpOrigin, :credentialId, "
|
|
":name, :iconDataURL, :originAllowlist, :dynamicAllowEndpoint, "
|
|
":userDataExpireTime,"
|
|
":token, :effectiveType, :modificationTime, :idpBaseDomain);"_ns;
|
|
|
|
nsCOMPtr<mozIStorageStatement> writeStmt;
|
|
nsresult rv = mMemoryDatabaseConnection->CreateStatement(
|
|
insertQuery, getter_AddRefs(writeStmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<mozIStorageStatement> readStmt;
|
|
rv = mDiskDatabaseConnection->CreateStatement(selectAllQuery,
|
|
getter_AddRefs(readStmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool hasResult;
|
|
while (NS_SUCCEEDED(readStmt->ExecuteStep(&hasResult)) && hasResult) {
|
|
nsCOMPtr<nsIVariant> modificationTime, userDataExpireTime, idpOrigin,
|
|
credentialId, idpBaseDomain, name, iconDataURL, originAllowlist,
|
|
dynamicAllowEndpoint, token, effectiveType;
|
|
|
|
// Read values from disk query
|
|
rv = readStmt->GetVariant(0, getter_AddRefs(idpOrigin));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(1, getter_AddRefs(credentialId));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(2, getter_AddRefs(name));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(3, getter_AddRefs(iconDataURL));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(4, getter_AddRefs(originAllowlist));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(5, getter_AddRefs(dynamicAllowEndpoint));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(6, getter_AddRefs(userDataExpireTime));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(7, getter_AddRefs(token));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(8, getter_AddRefs(effectiveType));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(9, getter_AddRefs(modificationTime));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetVariant(10, getter_AddRefs(idpBaseDomain));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Write values to memory database
|
|
rv = writeStmt->BindByName("idpOrigin"_ns, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("credentialId"_ns, credentialId);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("name"_ns, name);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("iconDataURL"_ns, iconDataURL);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("originAllowlist"_ns, originAllowlist);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("dynamicAllowEndpoint"_ns, dynamicAllowEndpoint);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("userDataExpireTime"_ns, userDataExpireTime);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("token"_ns, token);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("effectiveType"_ns, effectiveType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("modificationTime"_ns, modificationTime);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindByName("idpBaseDomain"_ns, idpBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
IdentityCredentialStorageService::LoadHeavyweightMemoryTableFromDisk() {
|
|
MOZ_ASSERT(!NS_IsMainThread(),
|
|
"Must not load the table from disk in the main thread.");
|
|
auto constexpr selectAllQuery =
|
|
"SELECT rpOrigin, idpOrigin, credentialId, registered, allowLogout, "
|
|
"modificationTime, rpBaseDomain FROM identity;"_ns;
|
|
auto constexpr insertQuery =
|
|
"INSERT INTO identity(rpOrigin, idpOrigin, credentialId, registered, "
|
|
"allowLogout, modificationTime, rpBaseDomain) VALUES (?1, ?2, ?3, ?4, "
|
|
"?5, ?6, ?7);"_ns;
|
|
|
|
nsCOMPtr<mozIStorageStatement> writeStmt;
|
|
nsresult rv = mMemoryDatabaseConnection->CreateStatement(
|
|
insertQuery, getter_AddRefs(writeStmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<mozIStorageStatement> readStmt;
|
|
rv = mDiskDatabaseConnection->CreateStatement(selectAllQuery,
|
|
getter_AddRefs(readStmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool hasResult;
|
|
while (NS_SUCCEEDED(readStmt->ExecuteStep(&hasResult)) && hasResult) {
|
|
int64_t registered, allowLogout, modificationTime;
|
|
nsCString rpOrigin, idpOrigin, credentialID, rpBaseDomain;
|
|
|
|
// Read values from disk query
|
|
rv = readStmt->GetUTF8String(0, rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetUTF8String(1, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetUTF8String(2, credentialID);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetInt64(3, ®istered);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetInt64(4, &allowLogout);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetInt64(5, &modificationTime);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = readStmt->GetUTF8String(6, rpBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Write values to memory database
|
|
rv = writeStmt->BindUTF8StringByIndex(0, rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindUTF8StringByIndex(1, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindUTF8StringByIndex(2, credentialID);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindInt64ByIndex(3, registered);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindInt64ByIndex(4, allowLogout);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindInt64ByIndex(5, modificationTime);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->BindUTF8StringByIndex(6, rpBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = writeStmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult IdentityCredentialStorageService::LoadMemoryTableFromDisk() {
|
|
nsresult rv = LoadHeavyweightMemoryTableFromDisk();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return LoadLightweightMemoryTableFromDisk();
|
|
}
|
|
|
|
void IdentityCredentialStorageService::IncrementPendingWrites() {
|
|
MonitorAutoLock lock(mMonitor);
|
|
MOZ_ASSERT(mPendingWrites < std::numeric_limits<uint32_t>::max());
|
|
mPendingWrites++;
|
|
}
|
|
|
|
void IdentityCredentialStorageService::DecrementPendingWrites() {
|
|
MonitorAutoLock lock(mMonitor);
|
|
MOZ_ASSERT(mPendingWrites > 0);
|
|
mPendingWrites--;
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::UpsertData(
|
|
mozIStorageConnection* aDatabaseConnection, nsIPrincipal* aRPPrincipal,
|
|
nsIPrincipal* aIDPPrincipal, nsACString const& aCredentialID,
|
|
bool aRegistered, bool aAllowLogout) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
nsresult rv;
|
|
constexpr auto upsert_query =
|
|
"INSERT INTO identity(rpOrigin, idpOrigin, credentialId, "
|
|
"registered, allowLogout, modificationTime, rpBaseDomain)"
|
|
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"
|
|
"ON CONFLICT(rpOrigin, idpOrigin, credentialId)"
|
|
"DO UPDATE SET registered=excluded.registered, "
|
|
"allowLogout=excluded.allowLogout, "
|
|
"modificationTime=excluded.modificationTime"_ns;
|
|
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = aDatabaseConnection->CreateStatement(upsert_query, getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString rpOrigin;
|
|
rv = aRPPrincipal->GetOrigin(rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString idpOrigin;
|
|
rv = aIDPPrincipal->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString rpBaseDomain;
|
|
rv = aRPPrincipal->GetBaseDomain(rpBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(0, rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(1, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(2, aCredentialID);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindInt64ByIndex(3, aRegistered ? 1 : 0);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindInt64ByIndex(4, aAllowLogout ? 1 : 0);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindInt64ByIndex(5, MODIFIED_NOW);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(6, rpBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::DeleteData(
|
|
mozIStorageConnection* aDatabaseConnection, nsIPrincipal* aRPPrincipal,
|
|
nsIPrincipal* aIDPPrincipal, nsACString const& aCredentialID) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
auto constexpr deleteQuery =
|
|
"DELETE FROM identity WHERE rpOrigin=?1 AND idpOrigin=?2 AND "
|
|
"credentialId=?3"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
nsresult rv =
|
|
aDatabaseConnection->CreateStatement(deleteQuery, getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString rpOrigin;
|
|
rv = aRPPrincipal->GetOrigin(rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString idpOrigin;
|
|
rv = aIDPPrincipal->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(0, rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(1, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(2, aCredentialID);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::DisconnectData(
|
|
mozIStorageConnection* aDatabaseConnection, nsIPrincipal* aRPPrincipal,
|
|
nsIPrincipal* aIDPPrincipal) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
auto constexpr deleteQuery =
|
|
"DELETE FROM identity WHERE rpOrigin=?1 AND idpOrigin=?2"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
nsresult rv =
|
|
aDatabaseConnection->CreateStatement(deleteQuery, getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString rpOrigin;
|
|
rv = aRPPrincipal->GetOrigin(rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString idpOrigin;
|
|
rv = aIDPPrincipal->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(0, rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(1, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::UpsertLightweightData(
|
|
mozIStorageConnection* aDatabaseConnection,
|
|
const dom::IPCIdentityCredential& aData) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
NS_ENSURE_ARG_POINTER(aData.identityProvider());
|
|
nsresult rv;
|
|
constexpr auto upsertQuery =
|
|
"INSERT INTO lightweight_identity(idpOrigin, credentialId, "
|
|
"name, iconDataURL, originAllowlist, dynamicAllowEndpoint, "
|
|
"userDataExpireTime, token, effectiveType,"
|
|
"modificationTime, idpBaseDomain) VALUES (:idpOrigin, :credentialId, "
|
|
":name, "
|
|
":iconDataURL, :originAllowlist, :dynamicAllowEndpoint, "
|
|
":userDataExpireTime, :token, :effectiveType,"
|
|
":modificationTime, :idpBaseDomain)"
|
|
"ON CONFLICT(idpOrigin, credentialId)"
|
|
"DO UPDATE SET name=excluded.name, "
|
|
"iconDataURL=excluded.iconDataURL, "
|
|
"originAllowlist=excluded.originAllowlist, "
|
|
"dynamicAllowEndpoint=excluded.dynamicAllowEndpoint, "
|
|
"userDataExpireTime=excluded.userDataExpireTime, "
|
|
"token=excluded.token, "
|
|
"effectiveType=excluded.effectiveType, "
|
|
"modificationTime=excluded.modificationTime"_ns;
|
|
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = aDatabaseConnection->CreateStatement(upsertQuery, getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString idpOrigin;
|
|
rv = aData.identityProvider()->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString idpBaseDomain;
|
|
rv = aData.identityProvider()->GetBaseDomain(idpBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByName("idpOrigin"_ns, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByName("credentialId"_ns,
|
|
NS_ConvertUTF16toUTF8(aData.id()));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aData.name().isSome()) {
|
|
rv = stmt->BindUTF8StringByName("name"_ns, aData.name().value());
|
|
} else {
|
|
rv = stmt->BindNullByName("name"_ns);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aData.iconURL().isSome()) {
|
|
rv = stmt->BindUTF8StringByName("iconDataURL"_ns, aData.iconURL().value());
|
|
} else {
|
|
rv = stmt->BindNullByName("iconDataURL"_ns);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aData.effectiveOrigins().Length()) {
|
|
rv = stmt->BindUTF8StringByName(
|
|
"originAllowlist"_ns, StringJoin("|"_ns, aData.effectiveOrigins()));
|
|
} else {
|
|
rv = stmt->BindNullByName("originAllowlist"_ns);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aData.effectiveQueryURL().isSome()) {
|
|
rv = stmt->BindUTF8StringByName("dynamicAllowEndpoint"_ns,
|
|
aData.effectiveQueryURL().value());
|
|
} else {
|
|
rv = stmt->BindNullByName("dynamicAllowEndpoint"_ns);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aData.effectiveType().isSome()) {
|
|
rv = stmt->BindUTF8StringByName("effectiveType"_ns,
|
|
aData.effectiveType().value());
|
|
} else {
|
|
rv = stmt->BindNullByName("effectiveType"_ns);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aData.token().isSome()) {
|
|
rv = stmt->BindUTF8StringByName(
|
|
"token"_ns, NS_ConvertUTF16toUTF8(aData.token().value()));
|
|
} else {
|
|
rv = stmt->BindNullByName("token"_ns);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aData.infoExpiresAt().isSome() &&
|
|
aData.infoExpiresAt().value() <= INT64_MAX) {
|
|
rv = stmt->BindInt64ByName(
|
|
"userDataExpireTime"_ns,
|
|
static_cast<int64_t>(aData.infoExpiresAt().value()));
|
|
} else {
|
|
rv = stmt->BindNullByName("userDataExpireTime"_ns);
|
|
}
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindInt64ByName("modificationTime"_ns, MODIFIED_NOW);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByName("idpBaseDomain"_ns, idpBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return stmt->Execute();
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::DeleteLightweightData(
|
|
mozIStorageConnection* aDatabaseConnection,
|
|
const dom::IPCIdentityCredential& aData) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
NS_ENSURE_ARG_POINTER(aData.identityProvider());
|
|
nsresult rv;
|
|
constexpr auto deleteQuery =
|
|
"DELETE FROM lightweight_identity WHERE"
|
|
"idpOrigin = ?2 AND credentialId = ?3;"_ns;
|
|
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = aDatabaseConnection->CreateStatement(deleteQuery, getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCString idpOrigin;
|
|
rv = aData.identityProvider()->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByName("idpOrigin"_ns, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByName("credentialId"_ns,
|
|
NS_ConvertUTF16toUTF8(aData.id()));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return stmt->Execute();
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::ClearData(
|
|
mozIStorageConnection* aDatabaseConnection) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
nsresult rv =
|
|
aDatabaseConnection->ExecuteSimpleSQL("DELETE FROM identity;"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aDatabaseConnection->ExecuteSimpleSQL(
|
|
"DELETE FROM lightweight_identity;"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
// static
|
|
nsresult
|
|
IdentityCredentialStorageService::DeleteDataFromOriginAttributesPattern(
|
|
mozIStorageConnection* aDatabaseConnection,
|
|
OriginAttributesPattern const& aOriginAttributesPattern) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
nsCOMPtr<mozIStorageFunction> patternMatchFunction(
|
|
new OriginAttrsPatternMatchOriginSQLFunction(aOriginAttributesPattern));
|
|
|
|
nsresult rv = aDatabaseConnection->CreateFunction(
|
|
"ORIGIN_ATTRS_PATTERN_MATCH_ORIGIN"_ns, 1, patternMatchFunction);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aDatabaseConnection->ExecuteSimpleSQL(
|
|
"DELETE FROM identity WHERE "
|
|
"ORIGIN_ATTRS_PATTERN_MATCH_ORIGIN(rpOrigin);"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aDatabaseConnection->ExecuteSimpleSQL(
|
|
"DELETE FROM lightweight_identity WHERE "
|
|
"ORIGIN_ATTRS_PATTERN_MATCH_ORIGIN(idpOrigin);"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = aDatabaseConnection->RemoveFunction(
|
|
"ORIGIN_ATTRS_PATTERN_MATCH_ORIGIN"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::DeleteDataFromTimeRange(
|
|
mozIStorageConnection* aDatabaseConnection, int64_t aStart, int64_t aEnd) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
auto constexpr deleteTimeQuery =
|
|
"DELETE FROM identity WHERE modificationTime > ?1 and modificationTime "
|
|
"< ?2"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
nsresult rv = aDatabaseConnection->CreateStatement(deleteTimeQuery,
|
|
getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindInt64ByIndex(0, aStart);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindInt64ByIndex(1, aEnd);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
auto constexpr deleteTimeQueryLightweight =
|
|
"DELETE FROM lightweight_identity WHERE modificationTime > ?1 and "
|
|
"modificationTime "
|
|
"< ?2"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmtLightweight;
|
|
rv = aDatabaseConnection->CreateStatement(deleteTimeQueryLightweight,
|
|
getter_AddRefs(stmtLightweight));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmtLightweight->BindInt64ByIndex(0, aStart);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmtLightweight->BindInt64ByIndex(1, aEnd);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return stmtLightweight->Execute();
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::DeleteDataFromPrincipal(
|
|
mozIStorageConnection* aDatabaseConnection, nsIPrincipal* aPrincipal) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
NS_ENSURE_ARG_POINTER(aPrincipal);
|
|
|
|
nsCString origin;
|
|
nsresult rv = aPrincipal->GetOrigin(origin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
auto constexpr deletePrincipalQuery =
|
|
"DELETE FROM identity WHERE rpOrigin=?1"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = aDatabaseConnection->CreateStatement(deletePrincipalQuery,
|
|
getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(0, origin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
auto constexpr deletePrincipalQueryLightweight =
|
|
"DELETE FROM lightweight_identity WHERE idpOrigin=:idpOrigin"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmtLightweight;
|
|
rv = aDatabaseConnection->CreateStatement(deletePrincipalQueryLightweight,
|
|
getter_AddRefs(stmtLightweight));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmtLightweight->BindUTF8StringByName("idpOrigin"_ns, origin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return stmtLightweight->Execute();
|
|
}
|
|
|
|
// static
|
|
nsresult IdentityCredentialStorageService::DeleteDataFromBaseDomain(
|
|
mozIStorageConnection* aDatabaseConnection, nsACString const& aBaseDomain) {
|
|
NS_ENSURE_ARG_POINTER(aDatabaseConnection);
|
|
|
|
auto constexpr deleteBaseDomainQuery =
|
|
"DELETE FROM identity WHERE rpBaseDomain=?1"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
nsresult rv = aDatabaseConnection->CreateStatement(deleteBaseDomainQuery,
|
|
getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(0, aBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->Execute();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
auto constexpr deleteBaseDomainQueryLightweight =
|
|
"DELETE FROM lightweight_identity WHERE idpBaseDomain=?1"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmtLightweight;
|
|
rv = aDatabaseConnection->CreateStatement(deleteBaseDomainQueryLightweight,
|
|
getter_AddRefs(stmtLightweight));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmtLightweight->BindUTF8StringByIndex(0, aBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return stmtLightweight->Execute();
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::SetState(
|
|
nsIPrincipal* aRPPrincipal, nsIPrincipal* aIDPPrincipal,
|
|
nsACString const& aCredentialID, bool aRegistered, bool aAllowLogout) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(aRPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = UpsertData(mMemoryDatabaseConnection, aRPPrincipal, aIDPPrincipal,
|
|
aCredentialID, aRegistered, aAllowLogout);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
RefPtr<nsIPrincipal> rpPrincipal = aRPPrincipal;
|
|
RefPtr<nsIPrincipal> idpPrincipal = aIDPPrincipal;
|
|
nsCString credentialID(aCredentialID);
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self, rpPrincipal, idpPrincipal, credentialID,
|
|
aRegistered, aAllowLogout]() {
|
|
nsresult rv = UpsertData(
|
|
self->mDiskDatabaseConnection, rpPrincipal,
|
|
idpPrincipal, credentialID, aRegistered,
|
|
aAllowLogout);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::GetState(
|
|
nsIPrincipal* aRPPrincipal, nsIPrincipal* aIDPPrincipal,
|
|
nsACString const& aCredentialID, bool* aRegistered, bool* aAllowLogout) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(aRPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
auto constexpr selectQuery =
|
|
"SELECT registered, allowLogout FROM identity WHERE rpOrigin=?1 AND "
|
|
"idpOrigin=?2 AND credentialId=?3"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = mMemoryDatabaseConnection->CreateStatement(selectQuery,
|
|
getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCString rpOrigin;
|
|
nsCString idpOrigin;
|
|
rv = aRPPrincipal->GetOrigin(rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aIDPPrincipal->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = stmt->BindUTF8StringByIndex(0, rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(1, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(2, aCredentialID);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool hasResult;
|
|
// If we find a result, return it
|
|
if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
|
|
int64_t registeredInt, allowLogoutInt;
|
|
rv = stmt->GetInt64(0, ®isteredInt);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->GetInt64(1, &allowLogoutInt);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
*aRegistered = registeredInt != 0;
|
|
*aAllowLogout = allowLogoutInt != 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
// The tuple was not found on disk or in memory, use the defaults.
|
|
*aRegistered = false;
|
|
*aAllowLogout = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::Delete(
|
|
nsIPrincipal* aRPPrincipal, nsIPrincipal* aIDPPrincipal,
|
|
nsACString const& aCredentialID) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(aRPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = DeleteData(mMemoryDatabaseConnection, aRPPrincipal, aIDPPrincipal,
|
|
aCredentialID);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
RefPtr<nsIPrincipal> rpPrincipal = aRPPrincipal;
|
|
RefPtr<nsIPrincipal> idpPrincipal = aIDPPrincipal;
|
|
nsCString credentialID(aCredentialID);
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self, rpPrincipal, idpPrincipal, credentialID]() {
|
|
nsresult rv = DeleteData(
|
|
self->mDiskDatabaseConnection, rpPrincipal,
|
|
idpPrincipal, credentialID);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::Connected(
|
|
nsIPrincipal* aRPPrincipal, nsIPrincipal* aIDPPrincipal, bool* aConnected) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
*aConnected = false;
|
|
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(aRPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(aIDPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
auto constexpr selectQuery =
|
|
"SELECT registered FROM identity WHERE rpOrigin=?1 AND "
|
|
"idpOrigin=?2"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = mMemoryDatabaseConnection->CreateStatement(selectQuery,
|
|
getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCString rpOrigin;
|
|
nsCString idpOrigin;
|
|
rv = aRPPrincipal->GetOrigin(rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aIDPPrincipal->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = stmt->BindUTF8StringByIndex(0, rpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = stmt->BindUTF8StringByIndex(1, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool hasResult;
|
|
// If we find a result, return it
|
|
if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
|
|
int64_t registeredInt;
|
|
rv = stmt->GetInt64(0, ®isteredInt);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
*aConnected = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
*aConnected = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::Disconnect(
|
|
nsIPrincipal* aRPPrincipal, nsIPrincipal* aIDPPrincipal) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
NS_ENSURE_ARG_POINTER(aIDPPrincipal);
|
|
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(aRPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(aIDPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = DisconnectData(mMemoryDatabaseConnection, aRPPrincipal, aIDPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
RefPtr<nsIPrincipal> rpPrincipal = aRPPrincipal;
|
|
RefPtr<nsIPrincipal> idpPrincipal = aIDPPrincipal;
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self, rpPrincipal, idpPrincipal]() {
|
|
nsresult rv =
|
|
DisconnectData(self->mDiskDatabaseConnection,
|
|
rpPrincipal, idpPrincipal);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// Helper function to get credentials from the database and put them into an
|
|
// array of IPCIdentityCredentials. aStmt must be a SELECT query that give
|
|
// fields SELECT credentialId, name, iconDataURL, userDataExpireTime,
|
|
// originAllowList, dynamicAllowEndpoint, effectiveType, token, and [idpOrigin
|
|
// if aIDPPrincipal is null]
|
|
nsresult GetCredentialsHelper(
|
|
const nsCOMPtr<mozIStorageStatement>& aStmt,
|
|
const RefPtr<nsIPrincipal>& aIDPPrincipal,
|
|
nsTArray<mozilla::dom::IPCIdentityCredential>& aResult) {
|
|
bool hasResult;
|
|
nsresult rv;
|
|
// For each result, we append it to the array to return
|
|
while (NS_SUCCEEDED(aStmt->ExecuteStep(&hasResult)) && hasResult) {
|
|
nsAutoString id, name, iconDataURL, originAllowList, dynamicAllowEndpoint,
|
|
effectiveType, token, matchedOrigin;
|
|
int64_t userDataExpireTime;
|
|
rv = aStmt->GetString(0, id);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStmt->GetString(1, name);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStmt->GetString(2, iconDataURL);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStmt->GetInt64(3, &userDataExpireTime);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStmt->GetString(4, originAllowList);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStmt->GetString(5, dynamicAllowEndpoint);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStmt->GetString(6, effectiveType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = aStmt->GetString(7, token);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (!aIDPPrincipal) {
|
|
rv = aStmt->GetString(8, matchedOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
Maybe<nsCString> resultName, resultIconDataURL, resultDynamicAllowEndpoint,
|
|
resultEffectiveType;
|
|
Maybe<nsString> resultToken;
|
|
nsTArray<nsCString> allowListArray;
|
|
Maybe<int64_t> resultUserDataExpireTime;
|
|
RefPtr<nsIPrincipal> idpPrincipal;
|
|
|
|
if (!name.IsVoid() && name.Length()) {
|
|
resultName = Some(NS_ConvertUTF16toUTF8(name));
|
|
}
|
|
if (!iconDataURL.IsVoid() && iconDataURL.Length()) {
|
|
resultIconDataURL = Some(NS_ConvertUTF16toUTF8(iconDataURL));
|
|
}
|
|
if (!effectiveType.IsVoid() && effectiveType.Length()) {
|
|
resultEffectiveType = Some(NS_ConvertUTF16toUTF8(effectiveType));
|
|
}
|
|
if (!token.IsVoid() && token.Length()) {
|
|
resultToken = Some(token);
|
|
}
|
|
for (const auto& origin : originAllowList.Split('|')) {
|
|
allowListArray.AppendElement(NS_ConvertUTF16toUTF8(origin));
|
|
}
|
|
if (!dynamicAllowEndpoint.IsVoid() && dynamicAllowEndpoint.Length()) {
|
|
resultDynamicAllowEndpoint =
|
|
Some(NS_ConvertUTF16toUTF8(dynamicAllowEndpoint));
|
|
}
|
|
if (!aStmt->IsNull(3) && userDataExpireTime > 0) {
|
|
resultUserDataExpireTime = Some(userDataExpireTime);
|
|
}
|
|
if (aIDPPrincipal) {
|
|
idpPrincipal = aIDPPrincipal;
|
|
} else {
|
|
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
|
NS_ENSURE_TRUE(ssm, NS_ERROR_NOT_AVAILABLE);
|
|
rv = ssm->CreateContentPrincipalFromOrigin(
|
|
NS_ConvertUTF16toUTF8(matchedOrigin), getter_AddRefs(idpPrincipal));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
dom::IPCIdentityCredential result(
|
|
id, resultToken, resultName, resultIconDataURL, allowListArray,
|
|
resultDynamicAllowEndpoint, resultEffectiveType,
|
|
resultUserDataExpireTime, idpPrincipal);
|
|
aResult.AppendElement(result);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::
|
|
IdentityCredentialStorageService::GetIdentityCredentials(
|
|
nsTArray<RefPtr<nsIPrincipal>> const& aIDPPrincipals,
|
|
nsTArray<mozilla::dom::IPCIdentityCredential>& aResult) {
|
|
AssertIsOnMainThread();
|
|
|
|
nsresult rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
auto constexpr selectQuery =
|
|
"SELECT credentialId, name, iconDataURL, userDataExpireTime, originAllowList, dynamicAllowEndpoint, effectiveType, token FROM lightweight_identity WHERE idpOrigin=?1"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = mMemoryDatabaseConnection->CreateStatement(selectQuery,
|
|
getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
for (const RefPtr<nsIPrincipal>& idpPrincipal : aIDPPrincipals) {
|
|
rv = IdentityCredentialStorageService::ValidatePrincipal(idpPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCString idpOrigin;
|
|
rv = idpPrincipal->GetOrigin(idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = stmt->BindUTF8StringByIndex(0, idpOrigin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = GetCredentialsHelper(stmt, idpPrincipal, aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::
|
|
IdentityCredentialStorageService::GetIdentityCredentialsOfType(
|
|
const nsACString& aType,
|
|
nsTArray<mozilla::dom::IPCIdentityCredential>& aResult) {
|
|
AssertIsOnMainThread();
|
|
|
|
nsresult rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
auto constexpr selectQuery =
|
|
"SELECT credentialId, name, iconDataURL, userDataExpireTime, originAllowList, dynamicAllowEndpoint, effectiveType, token, idpOrigin FROM lightweight_identity WHERE effectiveType=?1"_ns;
|
|
nsCOMPtr<mozIStorageStatement> stmt;
|
|
rv = mMemoryDatabaseConnection->CreateStatement(selectQuery,
|
|
getter_AddRefs(stmt));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = stmt->BindUTF8StringByIndex(0, aType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = GetCredentialsHelper(stmt, nullptr, aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::StoreIdentityCredential(
|
|
const mozilla::dom::IPCIdentityCredential& aCredential) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aCredential.identityProvider());
|
|
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = UpsertLightweightData(mMemoryDatabaseConnection, aCredential);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
return mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction(
|
|
"IdentityCredentialStorageService::StoreIdentityCredential",
|
|
[self, aCredential]() {
|
|
nsresult rv = UpsertLightweightData(self->mDiskDatabaseConnection,
|
|
aCredential);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::DeleteIdentityCredential(
|
|
const mozilla::dom::IPCIdentityCredential& aCredential) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aCredential.identityProvider());
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = DeleteLightweightData(mMemoryDatabaseConnection, aCredential);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
return mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction(
|
|
"IdentityCredentialStorageService::DeleteIdentityCredential",
|
|
[self, aCredential]() {
|
|
nsresult rv = DeleteLightweightData(self->mDiskDatabaseConnection,
|
|
aCredential);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::Clear() {
|
|
AssertIsOnMainThread();
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = ClearData(mMemoryDatabaseConnection);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self]() {
|
|
nsresult rv =
|
|
ClearData(self->mDiskDatabaseConnection);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IdentityCredentialStorageService::DeleteFromOriginAttributesPattern(
|
|
nsAString const& aOriginAttributesPattern) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_FALSE(aOriginAttributesPattern.IsEmpty(), NS_ERROR_FAILURE);
|
|
OriginAttributesPattern oaPattern;
|
|
if (!oaPattern.Init(aOriginAttributesPattern)) {
|
|
NS_ERROR("Could not parse the argument for OriginAttributes");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = DeleteDataFromOriginAttributesPattern(mMemoryDatabaseConnection,
|
|
oaPattern);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction(
|
|
"IdentityCredentialStorageService::Init",
|
|
[self, oaPattern]() {
|
|
nsresult rv = DeleteDataFromOriginAttributesPattern(
|
|
self->mDiskDatabaseConnection, oaPattern);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::DeleteFromTimeRange(
|
|
int64_t aStart, int64_t aEnd) {
|
|
AssertIsOnMainThread();
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = DeleteDataFromTimeRange(mMemoryDatabaseConnection, aStart, aEnd);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self, aStart, aEnd]() {
|
|
nsresult rv = DeleteDataFromTimeRange(
|
|
self->mDiskDatabaseConnection, aStart, aEnd);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::
|
|
IdentityCredentialStorageService::DeleteFromPrincipal(
|
|
nsIPrincipal* aRPPrincipal) {
|
|
AssertIsOnMainThread();
|
|
NS_ENSURE_ARG_POINTER(aRPPrincipal);
|
|
nsresult rv =
|
|
IdentityCredentialStorageService::ValidatePrincipal(aRPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = DeleteDataFromPrincipal(mMemoryDatabaseConnection, aRPPrincipal);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
RefPtr<nsIPrincipal> principal = aRPPrincipal;
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self, principal]() {
|
|
nsresult rv = DeleteDataFromPrincipal(
|
|
self->mDiskDatabaseConnection, principal);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP IdentityCredentialStorageService::DeleteFromBaseDomain(
|
|
nsACString const& aBaseDomain) {
|
|
AssertIsOnMainThread();
|
|
nsresult rv;
|
|
rv = WaitForInitialization();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = DeleteDataFromBaseDomain(mMemoryDatabaseConnection, aBaseDomain);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
IncrementPendingWrites();
|
|
RefPtr<IdentityCredentialStorageService> self = this;
|
|
nsCString baseDomain(aBaseDomain);
|
|
mBackgroundThread->Dispatch(
|
|
NS_NewRunnableFunction("IdentityCredentialStorageService::Init",
|
|
[self, baseDomain]() {
|
|
nsresult rv = DeleteDataFromBaseDomain(
|
|
self->mDiskDatabaseConnection, baseDomain);
|
|
self->DecrementPendingWrites();
|
|
NS_ENSURE_SUCCESS_VOID(rv);
|
|
}),
|
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
IdentityCredentialStorageService::Observe(nsISupports* aSubject,
|
|
const char* aTopic,
|
|
const char16_t* aData) {
|
|
AssertIsOnMainThread();
|
|
// Double check that we have the right topic.
|
|
if (!nsCRT::strcmp(aTopic, "last-pb-context-exited")) {
|
|
MonitorAutoLock lock(mMonitor);
|
|
if (mInitialized && mMemoryDatabaseConnection) {
|
|
nsCOMPtr<mozIStorageFunction> patternMatchFunction(
|
|
new PrivateBrowsingOriginSQLFunction());
|
|
nsresult rv = mMemoryDatabaseConnection->CreateFunction(
|
|
"PRIVATE_BROWSING_PATTERN_MATCH_ORIGIN"_ns, 1, patternMatchFunction);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = mMemoryDatabaseConnection->ExecuteSimpleSQL(
|
|
"DELETE FROM identity WHERE "
|
|
"PRIVATE_BROWSING_PATTERN_MATCH_ORIGIN(rpOrigin);"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = mMemoryDatabaseConnection->ExecuteSimpleSQL(
|
|
"DELETE FROM lightweight_identity WHERE "
|
|
"PRIVATE_BROWSING_PATTERN_MATCH_ORIGIN(idpOrigin);"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = mMemoryDatabaseConnection->RemoveFunction(
|
|
"PRIVATE_BROWSING_PATTERN_MATCH_ORIGIN"_ns);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(OriginAttrsPatternMatchOriginSQLFunction, mozIStorageFunction)
|
|
|
|
NS_IMETHODIMP
|
|
OriginAttrsPatternMatchOriginSQLFunction::OnFunctionCall(
|
|
mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult) {
|
|
nsresult rv;
|
|
|
|
nsAutoCString origin;
|
|
rv = aFunctionArguments->GetUTF8String(0, origin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCString originNoSuffix;
|
|
OriginAttributes oa;
|
|
bool parsedSuccessfully = oa.PopulateFromOrigin(origin, originNoSuffix);
|
|
NS_ENSURE_TRUE(parsedSuccessfully, NS_ERROR_FAILURE);
|
|
bool result = mPattern.Matches(oa);
|
|
|
|
RefPtr<nsVariant> outVar(new nsVariant());
|
|
rv = outVar->SetAsBool(result);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
outVar.forget(aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(PrivateBrowsingOriginSQLFunction, mozIStorageFunction)
|
|
|
|
NS_IMETHODIMP
|
|
PrivateBrowsingOriginSQLFunction::OnFunctionCall(
|
|
mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult) {
|
|
nsresult rv;
|
|
|
|
nsAutoCString origin;
|
|
rv = aFunctionArguments->GetUTF8String(0, origin);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool result = OriginAttributes::IsPrivateBrowsing(origin);
|
|
|
|
RefPtr<nsVariant> outVar(new nsVariant());
|
|
rv = outVar->SetAsBool(result);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
outVar.forget(aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla
|