Bug 1417266 - Cache calls to CryptAcquireContext r=mak

When running history imports, a large percentage of the time
is spend in CryptAcquireContext. This caches this for all guid
generation in the places system.

MozReview-Commit-ID: 43lig8F7Uww

--HG--
extra : rebase_source : adc5f8e90d7f16f935401cf20ff14040a9da10fd
This commit is contained in:
Doug Thayer 2017-11-21 11:28:40 -08:00
parent f733efea1a
commit 7d712c11e1
3 changed files with 44 additions and 19 deletions

View File

@ -209,19 +209,6 @@ ReverseString(const nsString& aInput, nsString& aReversed)
}
}
#ifdef XP_WIN
} // namespace places
} // namespace mozilla
// Included here because windows.h conflicts with the use of mozIStorageError
// above, but make sure that these are not included inside mozilla::places.
#include <windows.h>
#include <wincrypt.h>
namespace mozilla {
namespace places {
#endif
static
nsresult
GenerateRandomBytes(uint32_t aSize,
@ -229,13 +216,11 @@ GenerateRandomBytes(uint32_t aSize,
{
// On Windows, we'll use its built-in cryptographic API.
#if defined(XP_WIN)
const nsNavHistory* history = nsNavHistory::GetConstHistoryService();
HCRYPTPROV cryptoProvider;
BOOL rc = CryptAcquireContext(&cryptoProvider, 0, 0, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
if (rc) {
rc = CryptGenRandom(cryptoProvider, aSize, _buffer);
(void)CryptReleaseContext(cryptoProvider, 0);
}
nsresult rv = history->GetCryptoProvider(cryptoProvider);
NS_ENSURE_SUCCESS(rv, rv);
BOOL rc = CryptGenRandom(cryptoProvider, aSize, _buffer);
return rc ? NS_OK : NS_ERROR_FAILURE;
// On Unix, we'll just read in from /dev/urandom.

View File

@ -287,9 +287,19 @@ nsNavHistory::nsNavHistory()
, mLastCachedEndOfDay(0)
, mCanNotify(true)
, mCacheObservers("history-observers")
#ifdef XP_WIN
, mCryptoProviderInitialized(false)
#endif
{
NS_ASSERTION(!gHistoryService,
"Attempting to create two instances of the service!");
#ifdef XP_WIN
BOOL cryptoAcquired = CryptAcquireContext(&mCryptoProvider, 0, 0, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
if (cryptoAcquired) {
mCryptoProviderInitialized = true;
}
#endif
gHistoryService = this;
}
@ -300,8 +310,15 @@ nsNavHistory::~nsNavHistory()
// in case somebody creates an extra instance of the service.
NS_ASSERTION(gHistoryService == this,
"Deleting a non-singleton instance of the service");
if (gHistoryService == this)
gHistoryService = nullptr;
#ifdef XP_WIN
if (mCryptoProviderInitialized) {
Unused << CryptReleaseContext(mCryptoProvider, 0);
}
#endif
}

View File

@ -29,6 +29,11 @@
#include "mozilla/Attributes.h"
#include "mozilla/Atomics.h"
#ifdef XP_WIN
#include "WinUtils.h"
#include <wincrypt.h>
#endif
#define QUERYUPDATE_TIME 0
#define QUERYUPDATE_SIMPLE 1
#define QUERYUPDATE_COMPLEX 2
@ -488,6 +493,17 @@ public:
return mBatchLevel > 0;
}
#ifdef XP_WIN
/**
* Get the cached HCRYPTPROV initialized in the nsNavHistory constructor.
*/
nsresult GetCryptoProvider(HCRYPTPROV& aCryptoProvider) const {
NS_ENSURE_STATE(mCryptoProviderInitialized);
aCryptoProvider = mCryptoProvider;
return NS_OK;
}
#endif
private:
~nsNavHistory();
@ -642,6 +658,13 @@ protected:
// Used to enable and disable the observer notifications
bool mCanNotify;
nsCategoryCache<nsINavHistoryObserver> mCacheObservers;
// Used to cache the call to CryptAcquireContext, which is expensive
// when called thousands of times
#ifdef XP_WIN
HCRYPTPROV mCryptoProvider;
bool mCryptoProviderInitialized;
#endif
};