Bug 1290481 - P3: Record padding size into cache.sqlite. r=bkelly

MozReview-Commit-ID: 6poDeyErBjc

--HG--
extra : rebase_source : 2c53b2891cc6da4e1688bd7f93cf79314554e1f1
This commit is contained in:
Tom Tung 2017-07-10 16:54:20 +08:00
Родитель c9e3e0f1c0
Коммит 280d7fa36c
3 изменённых файлов: 119 добавлений и 17 удалений

103
dom/cache/DBSchema.cpp поставляемый
Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/HeadersBinding.h"
#include "mozilla/dom/InternalHeaders.h"
#include "mozilla/dom/InternalResponse.h"
#include "mozilla/dom/RequestBinding.h"
#include "mozilla/dom/ResponseBinding.h"
#include "mozilla/dom/cache/CacheTypes.h"
@ -320,6 +321,7 @@ static nsresult DeleteEntries(mozIStorageConnection* aConn,
const nsTArray<EntryId>& aEntryIdList,
nsTArray<nsID>& aDeletedBodyIdListOut,
nsTArray<IdCount>& aDeletedSecurityIdListOut,
int64_t* aDeletedPaddingSizeOut,
uint32_t aPos=0, int32_t aLen=-1);
static nsresult InsertSecurityInfo(mozIStorageConnection* aConn,
nsICryptoHash* aCrypto,
@ -599,10 +601,12 @@ CreateCacheId(mozIStorageConnection* aConn, CacheId* aCacheIdOut)
nsresult
DeleteCacheId(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<nsID>& aDeletedBodyIdListOut)
nsTArray<nsID>& aDeletedBodyIdListOut,
int64_t* aDeletedPaddingSizeOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aConn);
MOZ_DIAGNOSTIC_ASSERT(aDeletedPaddingSizeOut);
// Delete the bodies explicitly as we need to read out the body IDs
// anyway. These body IDs must be deleted one-by-one as content may
@ -612,10 +616,13 @@ DeleteCacheId(mozIStorageConnection* aConn, CacheId aCacheId,
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
AutoTArray<IdCount, 16> deletedSecurityIdList;
int64_t deletedPaddingSize = 0;
rv = DeleteEntries(aConn, matches, aDeletedBodyIdListOut,
deletedSecurityIdList);
deletedSecurityIdList, &deletedPaddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
*aDeletedPaddingSizeOut = deletedPaddingSize;
rv = DeleteSecurityInfoList(aConn, deletedSecurityIdList);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -793,10 +800,12 @@ CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
const nsID* aRequestBodyId,
const CacheResponse& aResponse,
const nsID* aResponseBodyId,
nsTArray<nsID>& aDeletedBodyIdListOut)
nsTArray<nsID>& aDeletedBodyIdListOut,
int64_t* aDeletedPaddingSizeOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aConn);
MOZ_DIAGNOSTIC_ASSERT(aDeletedPaddingSizeOut);
CacheQueryParams params(false, false, false, false,
NS_LITERAL_STRING(""));
@ -805,8 +814,9 @@ CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
AutoTArray<IdCount, 16> deletedSecurityIdList;
int64_t deletedPaddingSize = 0;
rv = DeleteEntries(aConn, matches, aDeletedBodyIdListOut,
deletedSecurityIdList);
deletedSecurityIdList, &deletedPaddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = InsertEntry(aConn, aCacheId, aRequest, aRequestBodyId, aResponse,
@ -818,6 +828,8 @@ CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
rv = DeleteSecurityInfoList(aConn, deletedSecurityIdList);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
*aDeletedPaddingSizeOut = deletedPaddingSize;
return rv;
}
@ -825,10 +837,12 @@ nsresult
CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
nsTArray<nsID>& aDeletedBodyIdListOut, bool* aSuccessOut)
nsTArray<nsID>& aDeletedBodyIdListOut,
int64_t* aDeletedPaddingSizeOut, bool* aSuccessOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aConn);
MOZ_DIAGNOSTIC_ASSERT(aDeletedPaddingSizeOut);
MOZ_DIAGNOSTIC_ASSERT(aSuccessOut);
*aSuccessOut = false;
@ -842,10 +856,13 @@ CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
}
AutoTArray<IdCount, 16> deletedSecurityIdList;
int64_t deletedPaddingSize = 0;
rv = DeleteEntries(aConn, matches, aDeletedBodyIdListOut,
deletedSecurityIdList);
deletedSecurityIdList, &deletedPaddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
*aDeletedPaddingSizeOut = deletedPaddingSize;
rv = DeleteSecurityInfoList(aConn, deletedSecurityIdList);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1334,10 +1351,12 @@ DeleteEntries(mozIStorageConnection* aConn,
const nsTArray<EntryId>& aEntryIdList,
nsTArray<nsID>& aDeletedBodyIdListOut,
nsTArray<IdCount>& aDeletedSecurityIdListOut,
int64_t* aDeletedPaddingSizeOut,
uint32_t aPos, int32_t aLen)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aConn);
MOZ_DIAGNOSTIC_ASSERT(aDeletedPaddingSizeOut);
if (aEntryIdList.IsEmpty()) {
return NS_OK;
@ -1352,24 +1371,36 @@ DeleteEntries(mozIStorageConnection* aConn,
// Sqlite limits the number of entries allowed for an IN clause,
// so split up larger operations.
if (aLen > kMaxEntriesPerStatement) {
int64_t overallDeletedPaddingSize = 0;
uint32_t curPos = aPos;
int32_t remaining = aLen;
while (remaining > 0) {
int64_t deletedPaddingSize = 0;
int32_t max = kMaxEntriesPerStatement;
int32_t curLen = std::min(max, remaining);
nsresult rv = DeleteEntries(aConn, aEntryIdList, aDeletedBodyIdListOut,
aDeletedSecurityIdListOut, curPos, curLen);
aDeletedSecurityIdListOut,
&deletedPaddingSize, curPos, curLen);
if (NS_FAILED(rv)) { return rv; }
MOZ_DIAGNOSTIC_ASSERT(INT64_MAX - deletedPaddingSize >=
overallDeletedPaddingSize);
overallDeletedPaddingSize += deletedPaddingSize;
curPos += curLen;
remaining -= curLen;
}
*aDeletedPaddingSizeOut += overallDeletedPaddingSize;
return NS_OK;
}
nsCOMPtr<mozIStorageStatement> state;
nsAutoCString query(
"SELECT request_body_id, response_body_id, response_security_info_id "
"SELECT "
"request_body_id, "
"response_body_id, "
"response_security_info_id, "
"response_padding_size "
"FROM entries WHERE id IN ("
);
AppendListParamsToQuery(query, aEntryIdList, aPos, aLen);
@ -1381,6 +1412,7 @@ DeleteEntries(mozIStorageConnection* aConn,
rv = BindListParamsToQuery(state, aEntryIdList, aPos, aLen);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
int64_t overallPaddingSize = 0;
bool hasMoreData = false;
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
// extract 0 to 2 nsID structs per row
@ -1424,8 +1456,24 @@ DeleteEntries(mozIStorageConnection* aConn,
aDeletedSecurityIdListOut.AppendElement(IdCount(securityId));
}
}
// It's possible to have null padding size for non-opaque response
rv = state->GetIsNull(3, &isNull);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
if (!isNull) {
int64_t paddingSize = 0;
rv = state->GetInt64(3, &paddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
MOZ_DIAGNOSTIC_ASSERT(paddingSize >= 0);
MOZ_DIAGNOSTIC_ASSERT(INT64_MAX - overallPaddingSize >= paddingSize);
overallPaddingSize += paddingSize;
}
}
*aDeletedPaddingSizeOut = overallPaddingSize;
// Dependent records removed via ON DELETE CASCADE
query = NS_LITERAL_CSTRING(
@ -1671,6 +1719,7 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
"response_body_id, "
"response_security_info_id, "
"response_principal_info, "
"response_padding_size, "
"cache_id "
") VALUES ("
":request_method, "
@ -1696,6 +1745,7 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
":response_body_id, "
":response_security_info_id, "
":response_principal_info, "
":response_padding_size, "
":cache_id "
");"
), getter_AddRefs(state));
@ -1813,6 +1863,18 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
serializedInfo);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
if (aResponse.paddingSize() == InternalResponse::UNKNOWN_PADDING_SIZE) {
MOZ_DIAGNOSTIC_ASSERT(aResponse.type() != ResponseType::Opaque);
rv = state->BindNullByName(NS_LITERAL_CSTRING("response_padding_size"));
} else {
MOZ_DIAGNOSTIC_ASSERT(aResponse.paddingSize() >= 0);
MOZ_DIAGNOSTIC_ASSERT(aResponse.type() == ResponseType::Opaque);
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("response_padding_size"),
aResponse.paddingSize());
}
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1898,7 +1960,7 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
responseUrlList[i]);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("entry_id"), entryId);
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("entry_id"), entryId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->Execute();
@ -1925,6 +1987,7 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
"entries.response_headers_guard, "
"entries.response_body_id, "
"entries.response_principal_info, "
"entries.response_padding_size, "
"security_info.data "
"FROM entries "
"LEFT OUTER JOIN security_info "
@ -1986,7 +2049,27 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
mozilla::ipc::ContentPrincipalInfo(attrs, void_t(), specNoSuffix);
}
rv = state->GetBlobAsUTF8String(6, aSavedResponseOut->mValue.channelInfo().securityInfo());
bool nullPadding = false;
rv = state->GetIsNull(6, &nullPadding);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
if (nullPadding) {
MOZ_DIAGNOSTIC_ASSERT(aSavedResponseOut->mValue.type() !=
ResponseType::Opaque);
aSavedResponseOut->mValue.paddingSize() =
InternalResponse::UNKNOWN_PADDING_SIZE;
} else {
MOZ_DIAGNOSTIC_ASSERT(aSavedResponseOut->mValue.type() ==
ResponseType::Opaque);
int64_t paddingSize = 0;
rv = state->GetInt64(6, &paddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
MOZ_DIAGNOSTIC_ASSERT(paddingSize >= 0);
aSavedResponseOut->mValue.paddingSize() = paddingSize;
}
rv = state->GetBlobAsUTF8String(7, aSavedResponseOut->mValue.channelInfo().securityInfo());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(

7
dom/cache/DBSchema.h поставляемый
Просмотреть файл

@ -42,7 +42,8 @@ CreateCacheId(mozIStorageConnection* aConn, CacheId* aCacheIdOut);
nsresult
DeleteCacheId(mozIStorageConnection* aConn, CacheId aCacheId,
nsTArray<nsID>& aDeletedBodyIdListOut);
nsTArray<nsID>& aDeletedBodyIdListOut,
int64_t* aDeletedPaddingSizeOut);
// TODO: Consider removing unused IsCacheOrphaned after writing cleanup code. (bug 1110446)
nsresult
@ -73,13 +74,15 @@ CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
const nsID* aRequestBodyId,
const CacheResponse& aResponse,
const nsID* aResponseBodyId,
nsTArray<nsID>& aDeletedBodyIdListOut);
nsTArray<nsID>& aDeletedBodyIdListOut,
int64_t* aDeletedPaddingSizeOut);
nsresult
CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
const CacheQueryParams& aParams,
nsTArray<nsID>& aDeletedBodyIdListOut,
int64_t* aDeletedPaddingSizeOut,
bool* aSuccessOut);
nsresult

26
dom/cache/Manager.cpp поставляемый
Просмотреть файл

@ -79,7 +79,9 @@ public:
for (uint32_t i = 0; i < orphanedCacheIdList.Length(); ++i) {
AutoTArray<nsID, 16> deletedBodyIdList;
rv = db::DeleteCacheId(aConn, orphanedCacheIdList[i], deletedBodyIdList);
int64_t deletedPaddingSize = 0;
rv = db::DeleteCacheId(aConn, orphanedCacheIdList[i], deletedBodyIdList,
&deletedPaddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = BodyDeleteFiles(aQuotaInfo, aDBDir, deletedBodyIdList);
@ -440,6 +442,7 @@ public:
: SyncDBAction(DBAction::Existing)
, mManager(aManager)
, mCacheId(aCacheId)
, mDeletedPaddingSize(0)
{ }
virtual nsresult
@ -449,7 +452,8 @@ public:
mozStorageTransaction trans(aConn, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
nsresult rv = db::DeleteCacheId(aConn, mCacheId, mDeletedBodyIdList);
nsresult rv = db::DeleteCacheId(aConn, mCacheId, mDeletedBodyIdList,
&mDeletedPaddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = trans.Commit();
@ -471,6 +475,8 @@ private:
RefPtr<Manager> mManager;
const CacheId mCacheId;
nsTArray<nsID> mDeletedBodyIdList;
// Track any pad amount associated with orphaned entries.
int64_t mDeletedPaddingSize;
};
// ----------------------------------------------------------------------------
@ -621,6 +627,7 @@ public:
, mExpectedAsyncCopyCompletions(1)
, mAsyncResult(NS_OK)
, mMutex("cache::Manager::CachePutAllAction")
, mDeletedPaddingSize(0)
{
MOZ_DIAGNOSTIC_ASSERT(!aPutList.IsEmpty());
MOZ_DIAGNOSTIC_ASSERT(aPutList.Length() == aRequestStreamList.Length());
@ -681,7 +688,6 @@ private:
}
}
// Always call OnAsyncCopyComplete() manually here. This covers the
// case where there is no async copying and also reports any startup
// errors correctly. If we hit an error, then OnAsyncCopyComplete()
@ -773,13 +779,16 @@ private:
e.mRequestStream ? &e.mRequestBodyId : nullptr,
e.mResponse,
e.mResponseStream ? &e.mResponseBodyId : nullptr,
mDeletedBodyIdList);
mDeletedBodyIdList, &mDeletedPaddingSize);
if (NS_WARN_IF(NS_FAILED(rv))) {
DoResolve(rv);
return;
}
}
// XXXtt: Write .padding file to the cache directory
// UpdateDirectoryFile(mDBDir);
rv = trans.Commit();
Unused << NS_WARN_IF(NS_FAILED(rv));
@ -980,6 +989,8 @@ private:
nsTArray<nsCOMPtr<nsISupports>> mCopyContextList;
Maybe<QuotaInfo> mQuotaInfo;
// Track any pad amount associated with overwritten entries.
int64_t mDeletedPaddingSize;
};
// ----------------------------------------------------------------------------
@ -993,6 +1004,7 @@ public:
, mCacheId(aCacheId)
, mArgs(aArgs)
, mSuccess(false)
, mDeletedPaddingSize(0)
{ }
virtual nsresult
@ -1004,7 +1016,7 @@ public:
nsresult rv = db::CacheDelete(aConn, mCacheId, mArgs.request(),
mArgs.params(), mDeletedBodyIdList,
&mSuccess);
&mDeletedPaddingSize, &mSuccess);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = trans.Commit();
@ -1033,6 +1045,8 @@ private:
const CacheDeleteArgs mArgs;
bool mSuccess;
nsTArray<nsID> mDeletedBodyIdList;
// Track any pad amount associated with deleted entries.
int64_t mDeletedPaddingSize;
};
// ----------------------------------------------------------------------------
@ -1282,6 +1296,8 @@ public:
return NS_OK;
}
// Don't delete the removing padding size here, we'll delete it on
// DeleteOrphanedCacheAction.
rv = db::StorageForgetCache(aConn, mNamespace, mArgs.key());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }