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/. */
7 #include "OriginInfo.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"
15 namespace mozilla::dom::quota
{
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
, bool aPersisted
,
27 bool aDirectoryExists
)
28 : mClientUsages(aClientUsages
.Clone()),
29 mGroupInfo(aGroupInfo
),
31 mStorageOrigin(aStorageOrigin
),
33 mAccessTime(aAccessTime
),
34 mIsPrivate(aIsPrivate
),
36 mPersisted(aPersisted
),
37 mIsExtension(StringBeginsWith(aOrigin
, "moz-extension://"_ns
)),
38 mDirectoryExists(aDirectoryExists
) {
39 MOZ_ASSERT(aGroupInfo
);
40 MOZ_ASSERT_IF(!aIsPrivate
, aOrigin
== aStorageOrigin
);
41 MOZ_ASSERT_IF(aIsPrivate
, aOrigin
!= aStorageOrigin
);
42 MOZ_ASSERT(aClientUsages
.Length() == Client::TypeMax());
43 MOZ_ASSERT_IF(aPersisted
,
44 aGroupInfo
->mPersistenceType
== PERSISTENCE_TYPE_DEFAULT
);
47 QuotaManager
* quotaManager
= QuotaManager::Get();
48 MOZ_ASSERT(quotaManager
);
51 for (Client::Type type
: quotaManager
->AllClientTypes()) {
52 AssertNoOverflow(usage
, aClientUsages
[type
].valueOr(0));
53 usage
+= aClientUsages
[type
].valueOr(0);
55 MOZ_ASSERT(aUsage
== usage
);
58 MOZ_COUNT_CTOR(OriginInfo
);
61 OriginMetadata
OriginInfo::FlattenToOriginMetadata() const {
62 return {mGroupInfo
->mGroupInfoPair
->Suffix(),
63 mGroupInfo
->mGroupInfoPair
->Group(),
67 mGroupInfo
->mPersistenceType
};
70 FullOriginMetadata
OriginInfo::LockedFlattenToFullOriginMetadata() const {
71 AssertCurrentThreadOwnsQuotaMutex();
73 return {FlattenToOriginMetadata(), mPersisted
, mAccessTime
};
76 nsresult
OriginInfo::LockedBindToStatement(
77 mozIStorageStatement
* aStatement
) const {
78 AssertCurrentThreadOwnsQuotaMutex();
79 MOZ_ASSERT(mGroupInfo
);
81 QM_TRY(MOZ_TO_RESULT(aStatement
->BindInt32ByName(
82 "repository_id"_ns
, mGroupInfo
->mPersistenceType
)));
84 QM_TRY(MOZ_TO_RESULT(aStatement
->BindUTF8StringByName(
85 "suffix"_ns
, mGroupInfo
->mGroupInfoPair
->Suffix())));
86 QM_TRY(MOZ_TO_RESULT(aStatement
->BindUTF8StringByName(
87 "group_"_ns
, mGroupInfo
->mGroupInfoPair
->Group())));
88 QM_TRY(MOZ_TO_RESULT(aStatement
->BindUTF8StringByName("origin"_ns
, mOrigin
)));
90 MOZ_ASSERT(!mIsPrivate
);
92 nsCString clientUsagesText
;
93 mClientUsages
.Serialize(clientUsagesText
);
96 aStatement
->BindUTF8StringByName("client_usages"_ns
, clientUsagesText
)));
97 QM_TRY(MOZ_TO_RESULT(aStatement
->BindInt64ByName("usage"_ns
, mUsage
)));
99 aStatement
->BindInt64ByName("last_access_time"_ns
, mAccessTime
)));
100 QM_TRY(MOZ_TO_RESULT(aStatement
->BindInt32ByName("accessed"_ns
, mAccessed
)));
102 MOZ_TO_RESULT(aStatement
->BindInt32ByName("persisted"_ns
, mPersisted
)));
107 void OriginInfo::LockedDecreaseUsage(Client::Type aClientType
, int64_t aSize
) {
108 AssertCurrentThreadOwnsQuotaMutex();
110 MOZ_ASSERT(mClientUsages
[aClientType
].isSome());
111 AssertNoUnderflow(mClientUsages
[aClientType
].value(), aSize
);
112 mClientUsages
[aClientType
] = Some(mClientUsages
[aClientType
].value() - aSize
);
114 AssertNoUnderflow(mUsage
, aSize
);
117 if (!LockedPersisted()) {
118 AssertNoUnderflow(mGroupInfo
->mUsage
, aSize
);
119 mGroupInfo
->mUsage
-= aSize
;
122 QuotaManager
* quotaManager
= QuotaManager::Get();
123 MOZ_ASSERT(quotaManager
);
125 AssertNoUnderflow(quotaManager
->mTemporaryStorageUsage
, aSize
);
126 quotaManager
->mTemporaryStorageUsage
-= aSize
;
129 void OriginInfo::LockedResetUsageForClient(Client::Type aClientType
) {
130 AssertCurrentThreadOwnsQuotaMutex();
132 uint64_t size
= mClientUsages
[aClientType
].valueOr(0);
134 mClientUsages
[aClientType
].reset();
136 AssertNoUnderflow(mUsage
, size
);
139 if (!LockedPersisted()) {
140 AssertNoUnderflow(mGroupInfo
->mUsage
, size
);
141 mGroupInfo
->mUsage
-= size
;
144 QuotaManager
* quotaManager
= QuotaManager::Get();
145 MOZ_ASSERT(quotaManager
);
147 AssertNoUnderflow(quotaManager
->mTemporaryStorageUsage
, size
);
148 quotaManager
->mTemporaryStorageUsage
-= size
;
151 UsageInfo
OriginInfo::LockedGetUsageForClient(Client::Type aClientType
) {
152 AssertCurrentThreadOwnsQuotaMutex();
154 // The current implementation of this method only supports DOMCACHE and LS,
155 // which only use DatabaseUsage. If this assertion is lifted, the logic below
157 MOZ_ASSERT(aClientType
== Client::Type::DOMCACHE
||
158 aClientType
== Client::Type::LS
||
159 aClientType
== Client::Type::FILESYSTEM
);
161 return UsageInfo
{DatabaseUsageType
{mClientUsages
[aClientType
]}};
164 void OriginInfo::LockedPersist() {
165 AssertCurrentThreadOwnsQuotaMutex();
166 MOZ_ASSERT(mGroupInfo
->mPersistenceType
== PERSISTENCE_TYPE_DEFAULT
);
167 MOZ_ASSERT(!mPersisted
);
171 // Remove Usage from GroupInfo
172 AssertNoUnderflow(mGroupInfo
->mUsage
, mUsage
);
173 mGroupInfo
->mUsage
-= mUsage
;
176 void OriginInfo::LockedDirectoryCreated() {
177 AssertCurrentThreadOwnsQuotaMutex();
178 MOZ_ASSERT(!mDirectoryExists
);
180 mDirectoryExists
= true;
183 } // namespace mozilla::dom::quota