mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 20:01:50 +00:00
Bug 1563023 - Part 2: Add support for getting origin usage from memory; r=asuth
This patch modifies getUsageForPrincipal to support getting origin usage from memory. Support for getting group usage is factored out to a standalone method called Estimate. Operations based on NormalOriginOperationBase can now avoid directory locking if they don't touch disk. Differential Revision: https://phabricator.services.mozilla.com/D38087 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
ca724248e4
commit
9ab967ef1e
@ -165,8 +165,8 @@ void QuotaUsageRequestChild::HandleResponse(
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mRequest);
|
||||
|
||||
RefPtr<OriginUsageResult> result = new OriginUsageResult(
|
||||
aResponse.usage(), aResponse.fileUsage(), aResponse.limit());
|
||||
RefPtr<OriginUsageResult> result =
|
||||
new OriginUsageResult(aResponse.usage(), aResponse.fileUsage());
|
||||
|
||||
RefPtr<nsVariant> variant = new nsVariant();
|
||||
variant->SetAsInterface(NS_GET_IID(nsIQuotaOriginUsageResult), result);
|
||||
@ -263,6 +263,19 @@ void QuotaRequestChild::HandleResponse(bool aResponse) {
|
||||
mRequest->SetResult(variant);
|
||||
}
|
||||
|
||||
void QuotaRequestChild::HandleResponse(const EstimateResponse& aResponse) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mRequest);
|
||||
|
||||
RefPtr<EstimateResult> result =
|
||||
new EstimateResult(aResponse.usage(), aResponse.limit());
|
||||
|
||||
RefPtr<nsVariant> variant = new nsVariant();
|
||||
variant->SetAsInterface(NS_GET_IID(nsIQuotaEstimateResult), result);
|
||||
|
||||
mRequest->SetResult(variant);
|
||||
}
|
||||
|
||||
void QuotaRequestChild::HandleResponse(const nsTArray<nsCString>& aResponse) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mRequest);
|
||||
@ -325,6 +338,10 @@ mozilla::ipc::IPCResult QuotaRequestChild::Recv__delete__(
|
||||
HandleResponse(aResponse.get_PersistedResponse().persisted());
|
||||
break;
|
||||
|
||||
case RequestResponse::TEstimateResponse:
|
||||
HandleResponse(aResponse.get_EstimateResponse());
|
||||
break;
|
||||
|
||||
case RequestResponse::TListInitializedOriginsResponse:
|
||||
HandleResponse(aResponse.get_ListInitializedOriginsResponse().origins());
|
||||
break;
|
||||
|
@ -129,6 +129,8 @@ class QuotaRequestChild final : public PQuotaRequestChild {
|
||||
|
||||
void HandleResponse(bool aResponse);
|
||||
|
||||
void HandleResponse(const EstimateResponse& aResponse);
|
||||
|
||||
void HandleResponse(const nsTArray<nsCString>& aResponse);
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
|
@ -868,7 +868,6 @@ class OriginOperationBase : public BackgroundThreadObject, public Runnable {
|
||||
bool mActorDestroyed;
|
||||
|
||||
protected:
|
||||
bool mNeedsMainThreadInit;
|
||||
bool mNeedsQuotaManagerInit;
|
||||
|
||||
public:
|
||||
@ -892,7 +891,6 @@ class OriginOperationBase : public BackgroundThreadObject, public Runnable {
|
||||
mResultCode(NS_OK),
|
||||
mState(State_Initial),
|
||||
mActorDestroyed(false),
|
||||
mNeedsMainThreadInit(false),
|
||||
mNeedsQuotaManagerInit(false) {}
|
||||
|
||||
// Reference counted.
|
||||
@ -991,6 +989,7 @@ class NormalOriginOperationBase : public OriginOperationBase,
|
||||
Nullable<Client::Type> mClientType;
|
||||
mozilla::Atomic<bool> mCanceled;
|
||||
const bool mExclusive;
|
||||
bool mNeedsDirectoryLocking;
|
||||
|
||||
public:
|
||||
void RunImmediately() {
|
||||
@ -1004,7 +1003,8 @@ class NormalOriginOperationBase : public OriginOperationBase,
|
||||
const OriginScope& aOriginScope, bool aExclusive)
|
||||
: mPersistenceType(aPersistenceType),
|
||||
mOriginScope(aOriginScope),
|
||||
mExclusive(aExclusive) {
|
||||
mExclusive(aExclusive),
|
||||
mNeedsDirectoryLocking(true) {
|
||||
AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
@ -1186,23 +1186,16 @@ class GetUsageOp final : public QuotaUsageRequestBase,
|
||||
};
|
||||
|
||||
class GetOriginUsageOp final : public QuotaUsageRequestBase {
|
||||
// If mGetGroupUsage is false, we use mUsageInfo to record the origin usage
|
||||
// and the file usage. Otherwise, we use it to record the group usage and the
|
||||
// limit.
|
||||
UsageInfo mUsageInfo;
|
||||
|
||||
const OriginUsageParams mParams;
|
||||
nsCString mSuffix;
|
||||
nsCString mGroup;
|
||||
bool mGetGroupUsage;
|
||||
bool mFromMemory;
|
||||
|
||||
public:
|
||||
explicit GetOriginUsageOp(const UsageRequestParams& aParams);
|
||||
|
||||
MOZ_IS_CLASS_INIT bool Init(Quota* aQuota) override;
|
||||
|
||||
private:
|
||||
~GetOriginUsageOp() {}
|
||||
~GetOriginUsageOp() = default;
|
||||
|
||||
virtual nsresult DoDirectoryWork(QuotaManager* aQuotaManager) override;
|
||||
|
||||
@ -1381,6 +1374,22 @@ class PersistOp final : public PersistRequestBase {
|
||||
void GetResponse(RequestResponse& aResponse) override;
|
||||
};
|
||||
|
||||
class EstimateOp final : public QuotaRequestBase {
|
||||
nsCString mGroup;
|
||||
uint64_t mUsage;
|
||||
uint64_t mLimit;
|
||||
|
||||
public:
|
||||
explicit EstimateOp(const RequestParams& aParams);
|
||||
|
||||
private:
|
||||
~EstimateOp() = default;
|
||||
|
||||
virtual nsresult DoDirectoryWork(QuotaManager* aQuotaManager) override;
|
||||
|
||||
void GetResponse(RequestResponse& aResponse) override;
|
||||
};
|
||||
|
||||
class ListInitializedOriginsOp final : public QuotaRequestBase,
|
||||
public TraverseRepositoryHelper {
|
||||
// XXX Bug 1521541 will make each origin has it's own state.
|
||||
@ -6071,36 +6080,55 @@ uint64_t QuotaManager::GetGroupLimit() const {
|
||||
std::max<uint64_t>(x, 10 MB));
|
||||
}
|
||||
|
||||
void QuotaManager::GetGroupUsageAndLimit(const nsACString& aGroup,
|
||||
UsageInfo* aUsageInfo) {
|
||||
uint64_t QuotaManager::GetGroupUsage(const nsACString& aGroup) {
|
||||
AssertIsOnIOThread();
|
||||
MOZ_ASSERT(aUsageInfo);
|
||||
|
||||
uint64_t usage = 0;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
aUsageInfo->SetLimit(GetGroupLimit());
|
||||
aUsageInfo->ResetUsage();
|
||||
|
||||
GroupInfoPair* pair;
|
||||
if (!mGroupInfoPairs.Get(aGroup, &pair)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate temporary group usage
|
||||
RefPtr<GroupInfo> temporaryGroupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
|
||||
if (temporaryGroupInfo) {
|
||||
aUsageInfo->AppendToDatabaseUsage(temporaryGroupInfo->mUsage);
|
||||
}
|
||||
|
||||
// Calculate default group usage
|
||||
RefPtr<GroupInfo> defaultGroupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
|
||||
if (defaultGroupInfo) {
|
||||
aUsageInfo->AppendToDatabaseUsage(defaultGroupInfo->mUsage);
|
||||
if (mGroupInfoPairs.Get(aGroup, &pair)) {
|
||||
for (const PersistenceType type : kBestEffortPersistenceTypes) {
|
||||
RefPtr<GroupInfo> groupInfo = pair->LockedGetGroupInfo(type);
|
||||
if (groupInfo) {
|
||||
AssertNoOverflow(usage, groupInfo->mUsage);
|
||||
usage += groupInfo->mUsage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
uint64_t QuotaManager::GetOriginUsage(const nsACString& aGroup,
|
||||
const nsACString& aOrigin) {
|
||||
AssertIsOnIOThread();
|
||||
|
||||
uint64_t usage = 0;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
GroupInfoPair* pair;
|
||||
if (mGroupInfoPairs.Get(aGroup, &pair)) {
|
||||
for (const PersistenceType type : kBestEffortPersistenceTypes) {
|
||||
RefPtr<GroupInfo> groupInfo = pair->LockedGetGroupInfo(type);
|
||||
if (groupInfo) {
|
||||
RefPtr<OriginInfo> originInfo =
|
||||
groupInfo->LockedGetOriginInfo(aOrigin);
|
||||
if (originInfo) {
|
||||
AssertNoOverflow(usage, originInfo->LockedUsage());
|
||||
usage += originInfo->LockedUsage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
void QuotaManager::NotifyStoragePressure(uint64_t aUsage) {
|
||||
@ -7131,8 +7159,16 @@ void NormalOriginOperationBase::Open() {
|
||||
|
||||
AdvanceState();
|
||||
|
||||
QuotaManager::Get()->OpenDirectoryInternal(mPersistenceType, mOriginScope,
|
||||
mClientType, mExclusive, this);
|
||||
if (mNeedsDirectoryLocking) {
|
||||
QuotaManager::Get()->OpenDirectoryInternal(mPersistenceType, mOriginScope,
|
||||
mClientType, mExclusive, this);
|
||||
} else {
|
||||
nsresult rv = DirectoryOpen();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Finish(rv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NormalOriginOperationBase::UnblockOpen() {
|
||||
@ -7141,7 +7177,9 @@ void NormalOriginOperationBase::UnblockOpen() {
|
||||
|
||||
SendResults();
|
||||
|
||||
mDirectoryLock = nullptr;
|
||||
if (mNeedsDirectoryLocking) {
|
||||
mDirectoryLock = nullptr;
|
||||
}
|
||||
|
||||
AdvanceState();
|
||||
}
|
||||
@ -7370,6 +7408,18 @@ bool Quota::VerifyRequestParams(const RequestParams& aParams) const {
|
||||
break;
|
||||
}
|
||||
|
||||
case RequestParams::TEstimateParams: {
|
||||
const EstimateParams& params = aParams.get_EstimateParams();
|
||||
|
||||
if (NS_WARN_IF(
|
||||
!QuotaManager::IsPrincipalInfoValid(params.principalInfo()))) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
@ -7506,6 +7556,10 @@ PQuotaRequestParent* Quota::AllocPQuotaRequestParent(
|
||||
actor = new PersistOp(aParams);
|
||||
break;
|
||||
|
||||
case RequestParams::TEstimateParams:
|
||||
actor = new EstimateOp(aParams);
|
||||
break;
|
||||
|
||||
case RequestParams::TListInitializedOriginsParams:
|
||||
actor = new ListInitializedOriginsOp();
|
||||
break;
|
||||
@ -7975,29 +8029,24 @@ void GetUsageOp::GetResponse(UsageRequestResponse& aResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams)
|
||||
: mParams(aParams.get_OriginUsageParams()),
|
||||
mGetGroupUsage(aParams.get_OriginUsageParams().getGroupUsage()) {
|
||||
GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aParams.type() == UsageRequestParams::TOriginUsageParams);
|
||||
}
|
||||
|
||||
bool GetOriginUsageOp::Init(Quota* aQuota) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aQuota);
|
||||
const OriginUsageParams& params = aParams.get_OriginUsageParams();
|
||||
|
||||
if (NS_WARN_IF(!QuotaUsageRequestBase::Init(aQuota))) {
|
||||
return false;
|
||||
QuotaManager::GetInfoFromValidatedPrincipalInfo(
|
||||
params.principalInfo(), &mSuffix, &mGroup, mOriginScope.AsOriginSetter());
|
||||
|
||||
mFromMemory = params.fromMemory();
|
||||
|
||||
// Overwrite NormalOriginOperationBase default values.
|
||||
if (mFromMemory) {
|
||||
mNeedsDirectoryLocking = false;
|
||||
}
|
||||
|
||||
// Figure out which origin we're dealing with.
|
||||
nsCString origin;
|
||||
QuotaManager::GetInfoFromValidatedPrincipalInfo(mParams.principalInfo(),
|
||||
&mSuffix, &mGroup, &origin);
|
||||
|
||||
mOriginScope.SetFromOrigin(origin);
|
||||
|
||||
return true;
|
||||
// Overwrite OriginOperationBase default values.
|
||||
mNeedsQuotaManagerInit = true;
|
||||
}
|
||||
|
||||
nsresult GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager) {
|
||||
@ -8008,23 +8057,28 @@ nsresult GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager) {
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mGetGroupUsage) {
|
||||
// Ensure temporary storage is initialized first. It will initialize all
|
||||
// origins for temporary storage including origins belonging to our group by
|
||||
// traversing the repositories. EnsureStorageIsInitialized is needed before
|
||||
// EnsureTemporaryStorageIsInitialized.
|
||||
if (mFromMemory) {
|
||||
// This must be called before EnsureTemporaryStorageIsInitialized.
|
||||
rv = aQuotaManager->EnsureStorageIsInitialized();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Ensure temporary storage is initialized. If temporary storage hasn't been
|
||||
// initialized yet, the method will initialize it by traversing the
|
||||
// repositories for temporary and default storage (including our origin).
|
||||
rv = aQuotaManager->EnsureTemporaryStorageIsInitialized();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Get cached usage and limit (the method doesn't have to stat any files).
|
||||
aQuotaManager->GetGroupUsageAndLimit(mGroup, &mUsageInfo);
|
||||
// Get cached usage (the method doesn't have to stat any files).
|
||||
uint64_t usage =
|
||||
aQuotaManager->GetOriginUsage(mGroup, mOriginScope.GetOrigin());
|
||||
|
||||
// File usage is not tracked in memory separately, so just add to the
|
||||
// database usage.
|
||||
mUsageInfo.AppendToDatabaseUsage(usage);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -8049,15 +8103,8 @@ void GetOriginUsageOp::GetResponse(UsageRequestResponse& aResponse) {
|
||||
|
||||
OriginUsageResponse usageResponse;
|
||||
|
||||
// We'll get the group usage when mGetGroupUsage is true and get the
|
||||
// origin usage when mGetGroupUsage is false.
|
||||
usageResponse.usage() = mUsageInfo.TotalUsage();
|
||||
|
||||
if (mGetGroupUsage) {
|
||||
usageResponse.limit() = mUsageInfo.Limit();
|
||||
} else {
|
||||
usageResponse.fileUsage() = mUsageInfo.FileUsage();
|
||||
}
|
||||
usageResponse.fileUsage() = mUsageInfo.FileUsage();
|
||||
|
||||
aResponse = usageResponse;
|
||||
}
|
||||
@ -8756,6 +8803,60 @@ void PersistOp::GetResponse(RequestResponse& aResponse) {
|
||||
aResponse = PersistResponse();
|
||||
}
|
||||
|
||||
EstimateOp::EstimateOp(const RequestParams& aParams)
|
||||
: QuotaRequestBase(/* aExclusive */ false), mUsage(0), mLimit(0) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aParams.type() == RequestParams::TEstimateParams);
|
||||
|
||||
QuotaManager::GetInfoFromValidatedPrincipalInfo(
|
||||
aParams.get_EstimateParams().principalInfo(), nullptr, &mGroup, nullptr);
|
||||
|
||||
// Overwrite NormalOriginOperationBase default values.
|
||||
mNeedsDirectoryLocking = false;
|
||||
|
||||
// Overwrite OriginOperationBase default values.
|
||||
mNeedsQuotaManagerInit = true;
|
||||
}
|
||||
|
||||
nsresult EstimateOp::DoDirectoryWork(QuotaManager* aQuotaManager) {
|
||||
AssertIsOnIOThread();
|
||||
|
||||
AUTO_PROFILER_LABEL("EstimateOp::DoDirectoryWork", OTHER);
|
||||
|
||||
// This must be called before EnsureTemporaryStorageIsInitialized.
|
||||
nsresult rv = aQuotaManager->EnsureStorageIsInitialized();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Ensure temporary storage is initialized. If temporary storage hasn't been
|
||||
// initialized yet, the method will initialize it by traversing the
|
||||
// repositories for temporary and default storage (including origins belonging
|
||||
// to our group).
|
||||
rv = aQuotaManager->EnsureTemporaryStorageIsInitialized();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Get cached usage (the method doesn't have to stat any files).
|
||||
mUsage = aQuotaManager->GetGroupUsage(mGroup);
|
||||
|
||||
mLimit = aQuotaManager->GetGroupLimit();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void EstimateOp::GetResponse(RequestResponse& aResponse) {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
EstimateResponse estimateResponse;
|
||||
|
||||
estimateResponse.usage() = mUsage;
|
||||
estimateResponse.limit() = mLimit;
|
||||
|
||||
aResponse = estimateResponse;
|
||||
}
|
||||
|
||||
ListInitializedOriginsOp::ListInitializedOriginsOp()
|
||||
: QuotaRequestBase(/* aExclusive */ false), TraverseRepositoryHelper() {
|
||||
AssertIsOnOwningThread();
|
||||
|
@ -232,6 +232,48 @@ class OriginScope {
|
||||
|
||||
OriginScope Clone() { return OriginScope(mData); }
|
||||
|
||||
template <typename T, typename U>
|
||||
class Setter {
|
||||
typedef void (OriginScope::*Method)(const U& aOrigin);
|
||||
|
||||
OriginScope* mOriginScope;
|
||||
Method mMethod;
|
||||
T mData;
|
||||
|
||||
public:
|
||||
Setter(OriginScope* aOriginScope, Method aMethod)
|
||||
: mOriginScope(aOriginScope), mMethod(aMethod) {}
|
||||
|
||||
Setter(Setter&& aOther)
|
||||
: mOriginScope(aOther.mOriginScope),
|
||||
mMethod(aOther.mMethod),
|
||||
mData(std::move(aOther.mData)) {}
|
||||
|
||||
~Setter() { ((*mOriginScope).*mMethod)(mData); }
|
||||
|
||||
operator T&() { return mData; }
|
||||
|
||||
operator T*() { return &mData; }
|
||||
|
||||
private:
|
||||
Setter() = delete;
|
||||
Setter(const Setter&) = delete;
|
||||
Setter& operator=(const Setter&) = delete;
|
||||
Setter& operator=(const Setter&&) = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Magic helper for cases where you are calling a method that takes a
|
||||
* ns(A)CString outparam to write an origin into. This method returns a helper
|
||||
* temporary that returns the underlying string storage, then on the
|
||||
* destruction of the temporary at the conclusion of the call, automatically
|
||||
* invokes SetFromOrigin using the origin value that was written into the
|
||||
* string.
|
||||
*/
|
||||
Setter<nsCString, nsACString> AsOriginSetter() {
|
||||
return Setter<nsCString, nsACString>(this, &OriginScope::SetFromOrigin);
|
||||
}
|
||||
|
||||
private:
|
||||
// Move constructors
|
||||
explicit OriginScope(const Origin&& aOrigin) : mData(aOrigin) {}
|
||||
|
@ -48,7 +48,7 @@ struct AllUsageParams
|
||||
struct OriginUsageParams
|
||||
{
|
||||
PrincipalInfo principalInfo;
|
||||
bool getGroupUsage;
|
||||
bool fromMemory;
|
||||
};
|
||||
|
||||
union UsageRequestParams
|
||||
@ -100,6 +100,11 @@ struct PersistParams
|
||||
PrincipalInfo principalInfo;
|
||||
};
|
||||
|
||||
struct EstimateParams
|
||||
{
|
||||
PrincipalInfo principalInfo;
|
||||
};
|
||||
|
||||
struct ListInitializedOriginsParams
|
||||
{
|
||||
};
|
||||
@ -116,6 +121,7 @@ union RequestParams
|
||||
ResetAllParams;
|
||||
PersistedParams;
|
||||
PersistParams;
|
||||
EstimateParams;
|
||||
ListInitializedOriginsParams;
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,12 @@ struct PersistResponse
|
||||
{
|
||||
};
|
||||
|
||||
struct EstimateResponse
|
||||
{
|
||||
uint64_t usage;
|
||||
uint64_t limit;
|
||||
};
|
||||
|
||||
struct ListInitializedOriginsResponse
|
||||
{
|
||||
nsCString[] origins;
|
||||
@ -68,6 +74,7 @@ union RequestResponse
|
||||
ResetAllResponse;
|
||||
PersistedResponse;
|
||||
PersistResponse;
|
||||
EstimateResponse;
|
||||
ListInitializedOriginsResponse;
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,6 @@ struct OriginUsageResponse
|
||||
{
|
||||
uint64_t usage;
|
||||
uint64_t fileUsage;
|
||||
uint64_t limit;
|
||||
};
|
||||
|
||||
union UsageRequestResponse
|
||||
|
@ -22,6 +22,9 @@ enum PersistenceType {
|
||||
PERSISTENCE_TYPE_INVALID
|
||||
};
|
||||
|
||||
static const PersistenceType kBestEffortPersistenceTypes[] = {
|
||||
PERSISTENCE_TYPE_TEMPORARY, PERSISTENCE_TYPE_DEFAULT};
|
||||
|
||||
static const PersistenceType kAllPersistenceTypes[] = {
|
||||
PERSISTENCE_TYPE_PERSISTENT, PERSISTENCE_TYPE_TEMPORARY,
|
||||
PERSISTENCE_TYPE_DEFAULT};
|
||||
|
@ -384,7 +384,9 @@ class QuotaManager final : public BackgroundThreadObject {
|
||||
|
||||
uint64_t GetGroupLimit() const;
|
||||
|
||||
void GetGroupUsageAndLimit(const nsACString& aGroup, UsageInfo* aUsageInfo);
|
||||
uint64_t GetGroupUsage(const nsACString& aGroup);
|
||||
|
||||
uint64_t GetOriginUsage(const nsACString& aGroup, const nsACString& aOrigin);
|
||||
|
||||
void NotifyStoragePressure(uint64_t aUsage);
|
||||
|
||||
|
@ -500,7 +500,7 @@ QuotaManagerService::GetUsage(nsIQuotaUsageCallback* aCallback, bool aGetAll,
|
||||
NS_IMETHODIMP
|
||||
QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsIQuotaUsageCallback* aCallback,
|
||||
bool aGetGroupUsage,
|
||||
bool aFromMemory,
|
||||
nsIQuotaUsageRequest** _retval) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
@ -516,7 +516,7 @@ QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
|
||||
return rv;
|
||||
}
|
||||
|
||||
params.getGroupUsage() = aGetGroupUsage;
|
||||
params.fromMemory() = aFromMemory;
|
||||
|
||||
nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
|
||||
|
||||
@ -740,6 +740,33 @@ QuotaManagerService::Persist(nsIPrincipal* aPrincipal,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
QuotaManagerService::Estimate(nsIPrincipal* aPrincipal,
|
||||
nsIQuotaRequest** _retval) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
RefPtr<Request> request = new Request(aPrincipal);
|
||||
|
||||
EstimateParams params;
|
||||
|
||||
nsresult rv =
|
||||
CheckedPrincipalToPrincipalInfo(aPrincipal, params.principalInfo());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
|
||||
|
||||
rv = InitiateRequest(info);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
request.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
QuotaManagerService::ListInitializedOrigins(nsIQuotaCallback* aCallback,
|
||||
nsIQuotaRequest** _retval) {
|
||||
|
@ -49,9 +49,8 @@ UsageResult::GetLastAccessed(uint64_t* aLastAccessed) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OriginUsageResult::OriginUsageResult(uint64_t aUsage, uint64_t aFileUsage,
|
||||
uint64_t aLimit)
|
||||
: mUsage(aUsage), mFileUsage(aFileUsage), mLimit(aLimit) {}
|
||||
OriginUsageResult::OriginUsageResult(uint64_t aUsage, uint64_t aFileUsage)
|
||||
: mUsage(aUsage), mFileUsage(aFileUsage) {}
|
||||
|
||||
NS_IMPL_ISUPPORTS(OriginUsageResult, nsIQuotaOriginUsageResult)
|
||||
|
||||
@ -71,8 +70,21 @@ OriginUsageResult::GetFileUsage(uint64_t* aFileUsage) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EstimateResult::EstimateResult(uint64_t aUsage, uint64_t aLimit)
|
||||
: mUsage(aUsage), mLimit(aLimit) {}
|
||||
|
||||
NS_IMPL_ISUPPORTS(EstimateResult, nsIQuotaEstimateResult)
|
||||
|
||||
NS_IMETHODIMP
|
||||
OriginUsageResult::GetLimit(uint64_t* aLimit) {
|
||||
EstimateResult::GetUsage(uint64_t* aUsage) {
|
||||
MOZ_ASSERT(aUsage);
|
||||
|
||||
*aUsage = mUsage;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EstimateResult::GetLimit(uint64_t* aLimit) {
|
||||
MOZ_ASSERT(aLimit);
|
||||
|
||||
*aLimit = mLimit;
|
||||
|
@ -33,10 +33,9 @@ class UsageResult : public nsIQuotaUsageResult {
|
||||
class OriginUsageResult : public nsIQuotaOriginUsageResult {
|
||||
uint64_t mUsage;
|
||||
uint64_t mFileUsage;
|
||||
uint64_t mLimit;
|
||||
|
||||
public:
|
||||
OriginUsageResult(uint64_t aUsage, uint64_t aFileUsage, uint64_t aLimit);
|
||||
OriginUsageResult(uint64_t aUsage, uint64_t aFileUsage);
|
||||
|
||||
private:
|
||||
virtual ~OriginUsageResult() {}
|
||||
@ -45,6 +44,20 @@ class OriginUsageResult : public nsIQuotaOriginUsageResult {
|
||||
NS_DECL_NSIQUOTAORIGINUSAGERESULT
|
||||
};
|
||||
|
||||
class EstimateResult : public nsIQuotaEstimateResult {
|
||||
uint64_t mUsage;
|
||||
uint64_t mLimit;
|
||||
|
||||
public:
|
||||
EstimateResult(uint64_t aUsage, uint64_t aLimit);
|
||||
|
||||
private:
|
||||
virtual ~EstimateResult() {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIQUOTAESTIMATERESULT
|
||||
};
|
||||
|
||||
class InitializedOriginsResult : public nsIQuotaInitializedOriginsResult {
|
||||
nsCString mOrigin;
|
||||
|
||||
|
@ -27,8 +27,7 @@ namespace {
|
||||
|
||||
// This class is used to get quota usage, request persist and check persisted
|
||||
// status callbacks.
|
||||
class RequestResolver final : public nsIQuotaCallback,
|
||||
public nsIQuotaUsageCallback {
|
||||
class RequestResolver final : public nsIQuotaCallback {
|
||||
public:
|
||||
enum Type { Estimate, Persist, Persisted };
|
||||
|
||||
@ -65,7 +64,6 @@ class RequestResolver final : public nsIQuotaCallback,
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIQUOTACALLBACK
|
||||
NS_DECL_NSIQUOTAUSAGECALLBACK
|
||||
|
||||
private:
|
||||
~RequestResolver() {}
|
||||
@ -74,8 +72,7 @@ class RequestResolver final : public nsIQuotaCallback,
|
||||
|
||||
nsresult GetPersisted(nsIVariant* aResult);
|
||||
|
||||
template <typename T>
|
||||
nsresult OnCompleteOrUsageResult(T* aRequest);
|
||||
nsresult OnCompleteInternal(nsIQuotaRequest* aRequest);
|
||||
|
||||
nsresult Finish();
|
||||
};
|
||||
@ -164,24 +161,35 @@ class PersistentStoragePermissionRequest final
|
||||
~PersistentStoragePermissionRequest() = default;
|
||||
};
|
||||
|
||||
nsresult GetUsageForPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsIQuotaUsageCallback* aCallback,
|
||||
nsIQuotaUsageRequest** aRequest) {
|
||||
nsresult Estimate(nsIPrincipal* aPrincipal, nsIQuotaCallback* aCallback,
|
||||
nsIQuotaRequest** aRequest) {
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(aRequest);
|
||||
|
||||
// Firefox and Quota Manager have always used the schemeless origin group
|
||||
// (https://storage.spec.whatwg.org/#schemeless-origin-group) for quota limit
|
||||
// purposes. This has been to prevent a site/eTLD+1 from claiming more than
|
||||
// its fair share of storage through the use of sub-domains. Because the limit
|
||||
// is at the group level and the usage needs to make sense in the context of
|
||||
// that limit, we also expose the group usage. Bug 1374970 reflects this
|
||||
// reality and bug 1305665 tracks our plan to eliminate our use of groups for
|
||||
// this.
|
||||
|
||||
nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
|
||||
if (NS_WARN_IF(!qms)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
qms->GetUsageForPrincipal(aPrincipal, aCallback, true, aRequest);
|
||||
nsCOMPtr<nsIQuotaRequest> request;
|
||||
nsresult rv = qms->Estimate(aPrincipal, getter_AddRefs(request));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(request->SetCallback(aCallback));
|
||||
|
||||
request.forget(aRequest);
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
@ -275,9 +283,8 @@ already_AddRefed<Promise> ExecuteOpOnMainOrWorkerThread(
|
||||
RefPtr<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Estimate, promise);
|
||||
|
||||
RefPtr<nsIQuotaUsageRequest> request;
|
||||
aRv =
|
||||
GetUsageForPrincipal(principal, resolver, getter_AddRefs(request));
|
||||
RefPtr<nsIQuotaRequest> request;
|
||||
aRv = Estimate(principal, resolver, getter_AddRefs(request));
|
||||
|
||||
break;
|
||||
}
|
||||
@ -389,7 +396,7 @@ void RequestResolver::ResolveOrReject() {
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(RequestResolver, nsIQuotaUsageCallback, nsIQuotaCallback)
|
||||
NS_IMPL_ISUPPORTS(RequestResolver, nsIQuotaCallback)
|
||||
|
||||
nsresult RequestResolver::GetStorageEstimate(nsIVariant* aResult) {
|
||||
MOZ_ASSERT(aResult);
|
||||
@ -406,15 +413,14 @@ nsresult RequestResolver::GetStorageEstimate(nsIVariant* aResult) {
|
||||
|
||||
free(iid);
|
||||
|
||||
nsCOMPtr<nsIQuotaOriginUsageResult> originUsageResult =
|
||||
do_QueryInterface(supports);
|
||||
MOZ_ASSERT(originUsageResult);
|
||||
nsCOMPtr<nsIQuotaEstimateResult> estimateResult = do_QueryInterface(supports);
|
||||
MOZ_ASSERT(estimateResult);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
originUsageResult->GetUsage(&mStorageEstimate.mUsage.Construct()));
|
||||
estimateResult->GetUsage(&mStorageEstimate.mUsage.Construct()));
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
originUsageResult->GetLimit(&mStorageEstimate.mQuota.Construct()));
|
||||
estimateResult->GetLimit(&mStorageEstimate.mQuota.Construct()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -446,8 +452,7 @@ nsresult RequestResolver::GetPersisted(nsIVariant* aResult) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
nsresult RequestResolver::OnCompleteOrUsageResult(T* aRequest) {
|
||||
nsresult RequestResolver::OnCompleteInternal(nsIQuotaRequest* aRequest) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRequest);
|
||||
|
||||
@ -512,22 +517,7 @@ RequestResolver::OnComplete(nsIQuotaRequest* aRequest) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRequest);
|
||||
|
||||
mResultCode = OnCompleteOrUsageResult(aRequest);
|
||||
|
||||
nsresult rv = Finish();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RequestResolver::OnUsageResult(nsIQuotaUsageRequest* aRequest) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRequest);
|
||||
|
||||
mResultCode = OnCompleteOrUsageResult(aRequest);
|
||||
mResultCode = OnCompleteInternal(aRequest);
|
||||
|
||||
nsresult rv = Finish();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -567,9 +557,8 @@ bool EstimateWorkerMainThreadRunnable::MainThreadRun() {
|
||||
RefPtr<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Estimate, mProxy);
|
||||
|
||||
RefPtr<nsIQuotaUsageRequest> request;
|
||||
nsresult rv =
|
||||
GetUsageForPrincipal(principal, resolver, getter_AddRefs(request));
|
||||
RefPtr<nsIQuotaRequest> request;
|
||||
nsresult rv = Estimate(principal, resolver, getter_AddRefs(request));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
class UsageInfo {
|
||||
public:
|
||||
UsageInfo() : mDatabaseUsage(0), mFileUsage(0), mLimit(0) {}
|
||||
UsageInfo() : mDatabaseUsage(0), mFileUsage(0) {}
|
||||
|
||||
virtual ~UsageInfo() {}
|
||||
|
||||
@ -33,25 +33,16 @@ class UsageInfo {
|
||||
IncrementUsage(&mFileUsage, aUsage);
|
||||
}
|
||||
|
||||
void SetLimit(uint64_t aLimit) { mLimit = aLimit; }
|
||||
|
||||
uint64_t DatabaseUsage() { return mDatabaseUsage; }
|
||||
|
||||
uint64_t FileUsage() { return mFileUsage; }
|
||||
|
||||
uint64_t Limit() { return mLimit; }
|
||||
|
||||
uint64_t TotalUsage() {
|
||||
uint64_t totalUsage = mDatabaseUsage;
|
||||
IncrementUsage(&totalUsage, mFileUsage);
|
||||
return totalUsage;
|
||||
}
|
||||
|
||||
void ResetUsage() {
|
||||
mDatabaseUsage = 0;
|
||||
mFileUsage = 0;
|
||||
}
|
||||
|
||||
static void IncrementUsage(uint64_t* aUsage, uint64_t aDelta) {
|
||||
MOZ_ASSERT(aUsage);
|
||||
CheckedUint64 value = *aUsage;
|
||||
@ -66,7 +57,6 @@ class UsageInfo {
|
||||
private:
|
||||
uint64_t mDatabaseUsage;
|
||||
uint64_t mFileUsage;
|
||||
uint64_t mLimit;
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
@ -75,16 +75,18 @@ interface nsIQuotaManagerService : nsISupports
|
||||
* A principal for the origin whose usage is being queried.
|
||||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
* @param aGetGroupUsage
|
||||
* An optional flag to indicate whether getting group usage and limit
|
||||
* or origin usage and file usage. The default value is false.
|
||||
* @param aFromMemory
|
||||
* An optional flag to indicate whether the cached usage should be
|
||||
* obtained. The default value is false. Note that this operation may
|
||||
* still be delayed by other operations on the QM I/O thread that are
|
||||
* peforming I/O.
|
||||
* Note: Origin usage here represents total usage of an origin. However,
|
||||
* group usage here represents only non-persistent usage of a group.
|
||||
* cached usage here represents only non-persistent usage of an origin.
|
||||
*/
|
||||
[must_use] nsIQuotaUsageRequest
|
||||
getUsageForPrincipal(in nsIPrincipal aPrincipal,
|
||||
in nsIQuotaUsageCallback aCallback,
|
||||
[optional] in boolean aGetGroupUsage);
|
||||
[optional] in boolean aFromMemory);
|
||||
|
||||
/**
|
||||
* Schedules an asynchronous callback that will inspect all origins and
|
||||
@ -221,4 +223,23 @@ interface nsIQuotaManagerService : nsISupports
|
||||
*/
|
||||
[must_use] nsIQuotaRequest
|
||||
persist(in nsIPrincipal aPrincipal);
|
||||
|
||||
/**
|
||||
* Given an origin, asynchronously calculate its group quota usage and quota
|
||||
* limit. An origin's group is the set of all origins that share the same
|
||||
* eTLD+1. This method is intended to be used for our implementation of the
|
||||
* StorageManager.estimate() method. When we fix bug 1305665 and stop tracking
|
||||
* quota limits on a group basis, this method will switch to operating on
|
||||
* origins. Callers should strongly consider whether they want to be using
|
||||
* getUsageForPrincipal() instead.
|
||||
*
|
||||
* This mechanism uses cached quota values and does not perform any I/O on its
|
||||
* own, but it may be delayed by QuotaManager operations that do need to
|
||||
* perform I/O on the QuotaManager I/O thread.
|
||||
*
|
||||
* @param aPrincipal
|
||||
* A principal for the origin (group) which we want to estimate.
|
||||
*/
|
||||
[must_use] nsIQuotaRequest
|
||||
estimate(in nsIPrincipal aPrincipal);
|
||||
};
|
||||
|
@ -24,6 +24,12 @@ interface nsIQuotaOriginUsageResult : nsISupports
|
||||
readonly attribute unsigned long long usage;
|
||||
|
||||
readonly attribute unsigned long long fileUsage;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(9827fc69-7ea9-48ef-b30d-2e2ae0451ec0)]
|
||||
interface nsIQuotaEstimateResult : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long long usage;
|
||||
|
||||
readonly attribute unsigned long long limit;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user