Bug 1482812: Patch for turning on the origin parser check on both beta and release. r=janv

This patch, basically, turns the check. To avoid checking the same direcotries
multiple time, it creates a member hashtable |mValidOrigins| in QuotaManager and
use it in EnsureOriginDirectory(). Since it needs to use the member hashtable,
this patch also moves EnsureOriginDirectory() to become a QuotaManager member
function.

--HG--
extra : rebase_source : 170f749b07ca955e1dc41a627d339709381ffcad
This commit is contained in:
Tom Tung 2018-08-15 16:59:26 +02:00
parent e66bb71c21
commit 5b3f5f96b1
3 changed files with 75 additions and 50 deletions

View File

@ -32,7 +32,6 @@ support-files =
[include:xpcshell-shared.ini]
[test_bad_origin_directory.js]
skip-if = release_or_beta
[test_obsoleteOriginAttributesUpgrade.js]
[test_blob_file_backed.js]
[test_bug1056939.js]

View File

@ -2031,52 +2031,6 @@ EnsureDirectory(nsIFile* aDirectory, bool* aCreated)
return NS_OK;
}
nsresult
EnsureOriginDirectory(nsIFile* aDirectory, bool* aCreated)
{
AssertIsOnIOThread();
nsresult rv;
#ifndef RELEASE_OR_BETA
bool exists;
rv = aDirectory->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!exists) {
nsString leafName;
nsresult rv = aDirectory->GetLeafName(leafName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!leafName.EqualsLiteral(kChromeOrigin)) {
nsCString spec;
OriginAttributes attrs;
OriginParser::ResultType result =
OriginParser::ParseOrigin(NS_ConvertUTF16toUTF8(leafName),
spec,
&attrs);
if (NS_WARN_IF(result != OriginParser::ValidOrigin)) {
QM_WARNING("Preventing creation of a new origin directory which is not "
"supported by our origin parser or is obsolete!");
return NS_ERROR_FAILURE;
}
}
}
#endif
rv = EnsureDirectory(aDirectory, aCreated);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
enum FileFlag {
kTruncateFileFlag,
kUpdateFileFlag,
@ -5477,6 +5431,43 @@ QuotaManager::EnsureTemporaryStorageIsInitialized()
return rv;
}
nsresult
QuotaManager::EnsureOriginDirectory(nsIFile* aDirectory,
bool* aCreated)
{
AssertIsOnIOThread();
MOZ_ASSERT(aDirectory);
MOZ_ASSERT(aCreated);
bool exists;
nsresult rv = aDirectory->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!exists) {
nsString leafName;
rv = aDirectory->GetLeafName(leafName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!leafName.EqualsLiteral(kChromeOrigin) &&
!IsSanitizedOriginValid(NS_ConvertUTF16toUTF8(leafName))) {
QM_WARNING("Preventing creation of a new origin directory which is not "
"supported by our origin parser or is obsolete!");
return NS_ERROR_FAILURE;
}
}
rv = EnsureDirectory(aDirectory, aCreated);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
void
QuotaManager::OriginClearCompleted(PersistenceType aPersistenceType,
const nsACString& aOrigin)
@ -6035,6 +6026,29 @@ QuotaManager::GetDirectoryLockTable(PersistenceType aPersistenceType)
}
}
bool
QuotaManager::IsSanitizedOriginValid(const nsACString& aSanitizedOrigin)
{
AssertIsOnIOThread();
MOZ_ASSERT(!aSanitizedOrigin.Equals(kChromeOrigin));
bool valid;
if (auto entry = mValidOrigins.LookupForAdd(aSanitizedOrigin)) {
// We already parsed this sanitized origin string.
valid = entry.Data();
} else {
nsCString spec;
OriginAttributes attrs;
OriginParser::ResultType result =
OriginParser::ParseOrigin(aSanitizedOrigin, spec, &attrs);
valid = result == OriginParser::ValidOrigin;
entry.OrInsert([valid]() { return valid; });
}
return valid;
}
/*******************************************************************************
* Local class implementations
******************************************************************************/
@ -7937,7 +7951,7 @@ PersistOp::DoDirectoryWork(QuotaManager* aQuotaManager)
}
bool created;
rv = EnsureOriginDirectory(directory, &created);
rv = aQuotaManager->EnsureOriginDirectory(directory, &created);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

View File

@ -301,6 +301,10 @@ public:
nsresult
EnsureTemporaryStorageIsInitialized();
nsresult
EnsureOriginDirectory(nsIFile* aDirectory,
bool* aCreated);
void
OriginClearCompleted(PersistenceType aPersistenceType,
const nsACString& aOrigin);
@ -522,6 +526,9 @@ private:
DirectoryLockTable&
GetDirectoryLockTable(PersistenceType aPersistenceType);
bool
IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
static void
ShutdownTimerCallback(nsITimer* aTimer, void* aClosure);
@ -545,10 +552,15 @@ private:
// A timer that gets activated at shutdown to ensure we close all storages.
nsCOMPtr<nsITimer> mShutdownTimer;
// A list of all successfully initialized origins. This list isn't protected
// by any mutex but it is only ever touched on the IO thread.
// A list of all successfully initialized persistent origins. This list isn't
// protected by any mutex but it is only ever touched on the IO thread.
nsTArray<nsCString> mInitializedOrigins;
// A hash table that is used to cache origin parser results for given
// sanitized origin strings. This hash table isn't protected by any mutex but
// it is only ever touched on the IO thread.
nsDataHashtable<nsCStringHashKey, bool> mValidOrigins;
// This array is populated at initialization time and then never modified, so
// it can be iterated on any thread.
AutoTArray<RefPtr<Client>, Client::TYPE_MAX> mClients;