OriginInfo.cpp (6743B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "OriginInfo.h" 8 9 #include "GroupInfo.h" 10 #include "GroupInfoPair.h" 11 #include "mozilla/dom/quota/AssertionsImpl.h" 12 #include "mozilla/dom/quota/ResultExtensions.h" 13 #include "mozilla/dom/quota/UsageInfo.h" 14 15 namespace mozilla::dom::quota { 16 17 // This constructor is called from the "QuotaManager IO" thread and so we 18 // can't check if the principal has a WebExtensionPolicy instance associated 19 // to it, and even besides that if the extension is currently disabled (and so 20 // no WebExtensionPolicy instance would actually exist) its stored data 21 // shouldn't be cleared until the extension is uninstalled and so here we 22 // resort to check the origin scheme instead to initialize mIsExtension. 23 OriginInfo::OriginInfo(GroupInfo* aGroupInfo, const nsACString& aOrigin, 24 const nsACString& aStorageOrigin, bool aIsPrivate, 25 const ClientUsageArray& aClientUsages, uint64_t aUsage, 26 int64_t aAccessTime, int32_t aMaintenanceDate, 27 bool aPersisted, bool aDirectoryExists) 28 : mClientUsages(aClientUsages), 29 mGroupInfo(aGroupInfo), 30 mOrigin(aOrigin), 31 mStorageOrigin(aStorageOrigin), 32 mUsage(aUsage), 33 mAccessTime(aAccessTime), 34 mMaintenanceDate(aMaintenanceDate), 35 mIsPrivate(aIsPrivate), 36 mAccessed(false), 37 mPersisted(aPersisted), 38 mIsExtension(StringBeginsWith(aOrigin, "moz-extension://"_ns)), 39 mDirectoryExists(aDirectoryExists) { 40 MOZ_ASSERT(aGroupInfo); 41 MOZ_ASSERT_IF(!aIsPrivate, aOrigin == aStorageOrigin); 42 MOZ_ASSERT_IF(aIsPrivate, aOrigin != aStorageOrigin); 43 MOZ_ASSERT(aClientUsages.Length() == Client::TypeMax()); 44 MOZ_ASSERT_IF(aPersisted, 45 aGroupInfo->mPersistenceType == PERSISTENCE_TYPE_DEFAULT); 46 47 #ifdef DEBUG 48 QuotaManager* quotaManager = QuotaManager::Get(); 49 MOZ_ASSERT(quotaManager); 50 51 uint64_t usage = 0; 52 for (Client::Type type : quotaManager->AllClientTypes()) { 53 AssertNoOverflow(usage, aClientUsages[type].valueOr(0)); 54 usage += aClientUsages[type].valueOr(0); 55 } 56 MOZ_ASSERT(aUsage == usage); 57 #endif 58 59 MOZ_COUNT_CTOR(OriginInfo); 60 } 61 62 OriginMetadata OriginInfo::FlattenToOriginMetadata() const { 63 return {mGroupInfo->mGroupInfoPair->Suffix(), 64 mGroupInfo->mGroupInfoPair->Group(), 65 mOrigin, 66 mStorageOrigin, 67 mIsPrivate, 68 mGroupInfo->mPersistenceType}; 69 } 70 71 OriginStateMetadata OriginInfo::LockedFlattenToOriginStateMetadata() const { 72 AssertCurrentThreadOwnsQuotaMutex(); 73 74 return {mAccessTime, mMaintenanceDate, mAccessed, mPersisted}; 75 } 76 77 FullOriginMetadata OriginInfo::LockedFlattenToFullOriginMetadata() const { 78 AssertCurrentThreadOwnsQuotaMutex(); 79 80 return {FlattenToOriginMetadata(), LockedFlattenToOriginStateMetadata(), 81 mClientUsages, mUsage, kCurrentQuotaVersion}; 82 } 83 84 nsresult OriginInfo::LockedBindToStatement( 85 mozIStorageStatement* aStatement) const { 86 AssertCurrentThreadOwnsQuotaMutex(); 87 MOZ_ASSERT(mGroupInfo); 88 89 QM_TRY(MOZ_TO_RESULT(aStatement->BindInt32ByName( 90 "repository_id"_ns, mGroupInfo->mPersistenceType))); 91 92 QM_TRY(MOZ_TO_RESULT(aStatement->BindUTF8StringByName( 93 "suffix"_ns, mGroupInfo->mGroupInfoPair->Suffix()))); 94 QM_TRY(MOZ_TO_RESULT(aStatement->BindUTF8StringByName( 95 "group_"_ns, mGroupInfo->mGroupInfoPair->Group()))); 96 QM_TRY(MOZ_TO_RESULT(aStatement->BindUTF8StringByName("origin"_ns, mOrigin))); 97 98 MOZ_ASSERT(!mIsPrivate); 99 100 nsCString clientUsagesText; 101 mClientUsages.Serialize(clientUsagesText); 102 103 QM_TRY(MOZ_TO_RESULT( 104 aStatement->BindUTF8StringByName("client_usages"_ns, clientUsagesText))); 105 QM_TRY(MOZ_TO_RESULT(aStatement->BindInt64ByName("usage"_ns, mUsage))); 106 QM_TRY(MOZ_TO_RESULT( 107 aStatement->BindInt64ByName("last_access_time"_ns, mAccessTime))); 108 QM_TRY(MOZ_TO_RESULT(aStatement->BindInt32ByName("last_maintenance_date"_ns, 109 mMaintenanceDate))); 110 QM_TRY(MOZ_TO_RESULT(aStatement->BindInt32ByName("accessed"_ns, mAccessed))); 111 QM_TRY( 112 MOZ_TO_RESULT(aStatement->BindInt32ByName("persisted"_ns, mPersisted))); 113 114 return NS_OK; 115 } 116 117 void OriginInfo::LockedDecreaseUsage(Client::Type aClientType, int64_t aSize) { 118 AssertCurrentThreadOwnsQuotaMutex(); 119 120 MOZ_ASSERT(mClientUsages[aClientType].isSome()); 121 AssertNoUnderflow(mClientUsages[aClientType].value(), aSize); 122 mClientUsages[aClientType] = Some(mClientUsages[aClientType].value() - aSize); 123 124 AssertNoUnderflow(mUsage, aSize); 125 mUsage -= aSize; 126 127 if (!LockedPersisted()) { 128 AssertNoUnderflow(mGroupInfo->mUsage, aSize); 129 mGroupInfo->mUsage -= aSize; 130 } 131 132 QuotaManager* quotaManager = QuotaManager::Get(); 133 MOZ_ASSERT(quotaManager); 134 135 AssertNoUnderflow(quotaManager->mTemporaryStorageUsage, aSize); 136 quotaManager->mTemporaryStorageUsage -= aSize; 137 } 138 139 void OriginInfo::LockedResetUsageForClient(Client::Type aClientType) { 140 AssertCurrentThreadOwnsQuotaMutex(); 141 142 uint64_t size = mClientUsages[aClientType].valueOr(0); 143 144 mClientUsages[aClientType].reset(); 145 146 AssertNoUnderflow(mUsage, size); 147 mUsage -= size; 148 149 if (!LockedPersisted()) { 150 AssertNoUnderflow(mGroupInfo->mUsage, size); 151 mGroupInfo->mUsage -= size; 152 } 153 154 QuotaManager* quotaManager = QuotaManager::Get(); 155 MOZ_ASSERT(quotaManager); 156 157 AssertNoUnderflow(quotaManager->mTemporaryStorageUsage, size); 158 quotaManager->mTemporaryStorageUsage -= size; 159 } 160 161 UsageInfo OriginInfo::LockedGetUsageForClient(Client::Type aClientType) { 162 AssertCurrentThreadOwnsQuotaMutex(); 163 164 // The current implementation of this method only supports DOMCACHE and LS, 165 // which only use DatabaseUsage. If this assertion is lifted, the logic below 166 // must be adapted. 167 MOZ_ASSERT(aClientType == Client::Type::DOMCACHE || 168 aClientType == Client::Type::LS || 169 aClientType == Client::Type::FILESYSTEM); 170 171 return UsageInfo{DatabaseUsageType{mClientUsages[aClientType]}}; 172 } 173 174 void OriginInfo::LockedPersist() { 175 AssertCurrentThreadOwnsQuotaMutex(); 176 MOZ_ASSERT(mGroupInfo->mPersistenceType == PERSISTENCE_TYPE_DEFAULT); 177 MOZ_ASSERT(!mPersisted); 178 179 mPersisted = true; 180 181 // Remove Usage from GroupInfo 182 AssertNoUnderflow(mGroupInfo->mUsage, mUsage); 183 mGroupInfo->mUsage -= mUsage; 184 } 185 186 void OriginInfo::LockedDirectoryCreated() { 187 AssertCurrentThreadOwnsQuotaMutex(); 188 MOZ_ASSERT(!mDirectoryExists); 189 190 mDirectoryExists = true; 191 } 192 193 } // namespace mozilla::dom::quota