зеркало из https://github.com/mozilla/gecko-dev.git
back out f24c22852083 for xpcshell failures b=829832
--HG-- extra : rebase_source : 151e69e6a280c9c67e9b49d55c11aad1fc0def94
This commit is contained in:
Родитель
7bf4102824
Коммит
6cf98de946
|
@ -34,9 +34,7 @@ interface nsIFile;
|
|||
*
|
||||
* @remarks Implementations may require the consumer to always call Finish. If
|
||||
* the object reference is released without calling Finish, a memory
|
||||
* leak may occur, and the target file might be kept locked. All
|
||||
* public methods of the interface may only be called from the main
|
||||
* thread.
|
||||
* leak may occur, and the target file might be kept locked.
|
||||
*/
|
||||
[scriptable, uuid(f2fb4daf-0aba-4b30-9ec0-b7a83ce3b7ab)]
|
||||
interface nsIBackgroundFileSaver : nsISupports
|
||||
|
@ -51,22 +49,6 @@ interface nsIBackgroundFileSaver : nsISupports
|
|||
*/
|
||||
attribute nsIBackgroundFileSaverObserver observer;
|
||||
|
||||
/**
|
||||
* The SHA256 hash in raw bytes associated with the file that was downloaded.
|
||||
*
|
||||
* @remarks Reading this will throw NS_ERROR_NOT_AVAILABLE unless
|
||||
* sha256enabled is true and onSaveComplete has been called.
|
||||
*/
|
||||
readonly attribute ACString sha256Hash;
|
||||
|
||||
/**
|
||||
* Compute SHA256.
|
||||
*
|
||||
* @remarks This must be set on the main thread before the first call to
|
||||
* setTarget.
|
||||
*/
|
||||
void enableSha256();
|
||||
|
||||
/**
|
||||
* Sets the name of the output file to be written. The output file may
|
||||
* already exist, in which case it will be overwritten. The target can be
|
||||
|
|
|
@ -4,18 +4,11 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "pk11pub.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
#include "secoidt.h"
|
||||
|
||||
#include "BackgroundFileSaver.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIPipe.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
|
||||
#include "BackgroundFileSaver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -81,36 +74,13 @@ BackgroundFileSaver::BackgroundFileSaver()
|
|||
, mAssignedTarget(nullptr)
|
||||
, mAssignedTargetKeepPartial(false)
|
||||
, mAsyncCopyContext(nullptr)
|
||||
, mSha256Enabled(false)
|
||||
, mActualTarget(nullptr)
|
||||
, mActualTargetKeepPartial(false)
|
||||
, mDigestContext(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
BackgroundFileSaver::~BackgroundFileSaver()
|
||||
{
|
||||
destructorSafeDestroyNSSReference();
|
||||
shutdown(calledFromObject);
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundFileSaver::destructorSafeDestroyNSSReference()
|
||||
{
|
||||
nsNSSShutDownPreventionLock lock;
|
||||
if (isAlreadyShutDown()) {
|
||||
return;
|
||||
}
|
||||
if (mDigestContext) {
|
||||
mozilla::psm::PK11_DestroyContext_true(mDigestContext.forget());
|
||||
mDigestContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BackgroundFileSaver::virtualDestroyNSSReference()
|
||||
{
|
||||
destructorSafeDestroyNSSReference();
|
||||
}
|
||||
|
||||
// Called on the control thread.
|
||||
|
@ -156,6 +126,7 @@ NS_IMETHODIMP
|
|||
BackgroundFileSaver::SetTarget(nsIFile *aTarget, bool aKeepPartial)
|
||||
{
|
||||
NS_ENSURE_ARG(aTarget);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
aTarget->Clone(getter_AddRefs(mAssignedTarget));
|
||||
|
@ -196,33 +167,6 @@ BackgroundFileSaver::Finish(nsresult aStatus)
|
|||
return GetWorkerThreadAttention(NS_FAILED(aStatus));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BackgroundFileSaver::EnableSha256()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can't enable sha256 or initialize NSS off the main thread");
|
||||
mSha256Enabled = true;
|
||||
// Ensure Personal Security Manager is initialized. This is required for
|
||||
// PK11_* operations to work.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupports> nssDummy = do_GetService("@mozilla.org/psm;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BackgroundFileSaver::GetSha256Hash(nsACString& aHash)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Can't inspect sha256 off the main thread");
|
||||
// We acquire a lock because mSha256 is written on the worker thread.
|
||||
MutexAutoLock lock(mLock);
|
||||
if (mSha256.IsEmpty()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
aHash = mSha256;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Called on the control thread.
|
||||
nsresult
|
||||
BackgroundFileSaver::GetWorkerThreadAttention(bool aShouldInterruptCopy)
|
||||
|
@ -271,6 +215,7 @@ void
|
|||
BackgroundFileSaver::AsyncCopyCallback(void *aClosure, nsresult aStatus)
|
||||
{
|
||||
BackgroundFileSaver *self = (BackgroundFileSaver *)aClosure;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(self->mLock);
|
||||
|
||||
|
@ -320,6 +265,7 @@ BackgroundFileSaver::ProcessAttention()
|
|||
NS_CancelAsyncCopy(mAsyncCopyContext, NS_ERROR_ABORT);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Use the current shared state to determine the next operation to execute.
|
||||
rv = ProcessStateChange();
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -331,6 +277,7 @@ BackgroundFileSaver::ProcessAttention()
|
|||
mStatus = rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we notify completion now that the operation failed.
|
||||
CheckCompletion();
|
||||
}
|
||||
|
@ -352,7 +299,6 @@ BackgroundFileSaver::ProcessStateChange()
|
|||
// Get a copy of the current shared state for the worker thread.
|
||||
nsCOMPtr<nsIFile> target;
|
||||
bool targetKeepPartial;
|
||||
bool sha256Enabled = false;
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
|
@ -361,8 +307,6 @@ BackgroundFileSaver::ProcessStateChange()
|
|||
|
||||
// From now on, another attention event needs to be posted if state changes.
|
||||
mWorkerThreadAttentionRequested = false;
|
||||
|
||||
sha256Enabled = mSha256Enabled;
|
||||
}
|
||||
|
||||
// The target can only be null if it has never been assigned. In this case,
|
||||
|
@ -460,30 +404,6 @@ BackgroundFileSaver::ProcessStateChange()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Wrap the output stream in a hashing stream if hashing is enabled and NSS
|
||||
// hasn't been shut down.
|
||||
bool isShutDown = false;
|
||||
if (sha256Enabled && !mDigestContext) {
|
||||
nsNSSShutDownPreventionLock lock;
|
||||
if (!(isShutDown = isAlreadyShutDown())) {
|
||||
mDigestContext =
|
||||
PK11_CreateDigestContext(static_cast<SECOidTag>(SEC_OID_SHA256));
|
||||
NS_ENSURE_TRUE(mDigestContext, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(!sha256Enabled || mDigestContext || isShutDown,
|
||||
"Hashing enabled but creating digest context didn't work");
|
||||
if (mDigestContext) {
|
||||
// No need to acquire the NSS lock here, DigestOutputStream must acquire it
|
||||
// in any case before each asynchronous write. Constructing the
|
||||
// DigestOutputStream cannot fail. Passing mDigestContext to
|
||||
// DigestOutputStream is safe, because BackgroundFileSaver always outlives
|
||||
// the outputStream. BackgroundFileSaver is reference-counted before the
|
||||
// call to AsyncCopy, and mDigestContext is never destroyed before
|
||||
// AsyncCopyCallback.
|
||||
outputStream = new DigestOutputStream(outputStream, mDigestContext);
|
||||
}
|
||||
|
||||
// Start copying our input to the target file. No errors can be raised past
|
||||
// this point if the copy starts, since they should be handled by the thread.
|
||||
{
|
||||
|
@ -554,26 +474,11 @@ BackgroundFileSaver::CheckCompletion()
|
|||
mComplete = true;
|
||||
}
|
||||
|
||||
// Ensure we notify completion now that the operation finished.
|
||||
// Do a best-effort attempt to remove the file if required.
|
||||
if (failed && mActualTarget && !mActualTargetKeepPartial) {
|
||||
(void)mActualTarget->Remove(false);
|
||||
}
|
||||
|
||||
// Finish computing the hash
|
||||
if (!failed && mDigestContext) {
|
||||
nsNSSShutDownPreventionLock lock;
|
||||
if (!isAlreadyShutDown()) {
|
||||
Digest d;
|
||||
rv = d.End(SEC_OID_SHA256, mDigestContext);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MutexAutoLock lock(mLock);
|
||||
mSha256 = nsDependentCSubstring(char_ptr_cast(d.get().data),
|
||||
d.get().len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Post an event to notify that the operation completed.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &BackgroundFileSaver::NotifySaveComplete);
|
||||
|
@ -890,76 +795,5 @@ BackgroundFileSaverStreamListener::NotifySuspendOrResume()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DigestOutputStream
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(DigestOutputStream,
|
||||
nsIOutputStream)
|
||||
|
||||
DigestOutputStream::DigestOutputStream(nsIOutputStream* aStream,
|
||||
PK11Context* aContext) :
|
||||
mOutputStream(aStream)
|
||||
, mDigestContext(aContext)
|
||||
{
|
||||
MOZ_ASSERT(mDigestContext, "Can't have null digest context");
|
||||
MOZ_ASSERT(mOutputStream, "Can't have null output stream");
|
||||
}
|
||||
|
||||
DigestOutputStream::~DigestOutputStream()
|
||||
{
|
||||
shutdown(calledFromObject);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DigestOutputStream::Close()
|
||||
{
|
||||
return mOutputStream->Close();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DigestOutputStream::Flush()
|
||||
{
|
||||
return mOutputStream->Flush();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DigestOutputStream::Write(const char* aBuf, uint32_t aCount, uint32_t* retval)
|
||||
{
|
||||
nsNSSShutDownPreventionLock lock;
|
||||
if (isAlreadyShutDown()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult rv = MapSECStatus(PK11_DigestOp(mDigestContext,
|
||||
uint8_t_ptr_cast(aBuf), aCount));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mOutputStream->Write(aBuf, aCount, retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DigestOutputStream::WriteFrom(nsIInputStream* aFromStream,
|
||||
uint32_t aCount, uint32_t* retval)
|
||||
{
|
||||
// Not supported. We could read the stream to a buf, call DigestOp on the
|
||||
// result, seek back and pass the stream on, but it's not worth it since our
|
||||
// application (NS_AsyncCopy) doesn't invoke this on the sink.
|
||||
MOZ_NOT_REACHED("DigestOutputStream::WriteFrom not implemented");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DigestOutputStream::WriteSegments(nsReadSegmentFun aReader,
|
||||
void *aClosure, uint32_t aCount,
|
||||
uint32_t *retval)
|
||||
{
|
||||
MOZ_NOT_REACHED("DigestOutputStream::WriteSegments not implemented");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DigestOutputStream::IsNonBlocking(bool *retval)
|
||||
{
|
||||
return mOutputStream->IsNonBlocking(retval);
|
||||
}
|
||||
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -14,12 +14,10 @@
|
|||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNSSShutDown.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsIBackgroundFileSaver.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
|
||||
class nsIAsyncInputStream;
|
||||
class nsIThread;
|
||||
|
@ -27,13 +25,10 @@ class nsIThread;
|
|||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class DigestOutputStream;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// BackgroundFileSaver
|
||||
|
||||
class BackgroundFileSaver : public nsIBackgroundFileSaver,
|
||||
public nsNSSShutDownObject
|
||||
class BackgroundFileSaver : public nsIBackgroundFileSaver
|
||||
{
|
||||
public:
|
||||
NS_DECL_NSIBACKGROUNDFILESAVER
|
||||
|
@ -48,19 +43,9 @@ public:
|
|||
*/
|
||||
nsresult Init();
|
||||
|
||||
/**
|
||||
* Used by nsNSSShutDownList to manage nsNSSShutDownObjects.
|
||||
*/
|
||||
void virtualDestroyNSSReference();
|
||||
|
||||
protected:
|
||||
virtual ~BackgroundFileSaver();
|
||||
|
||||
/**
|
||||
* Helper function for managing NSS objects (mDigestContext).
|
||||
*/
|
||||
void destructorSafeDestroyNSSReference();
|
||||
|
||||
/**
|
||||
* Thread that constructed this object.
|
||||
*/
|
||||
|
@ -73,8 +58,7 @@ protected:
|
|||
|
||||
/**
|
||||
* Stream that receives data from derived classes. The received data will be
|
||||
* available to the worker thread through mPipeInputStream. This is an
|
||||
* instance of nsPipeOutputStream, not BackgroundFileSaverOutputStream.
|
||||
* available to the worker thread through mPipeInputStream.
|
||||
*/
|
||||
nsCOMPtr<nsIAsyncOutputStream> mPipeOutputStream;
|
||||
|
||||
|
@ -158,18 +142,6 @@ private:
|
|||
*/
|
||||
nsCOMPtr<nsISupports> mAsyncCopyContext;
|
||||
|
||||
/**
|
||||
* The SHA 256 hash in raw bytes of the downloaded file. This is written
|
||||
* by the worker thread but can be read on the main thread.
|
||||
*/
|
||||
nsAutoCString mSha256;
|
||||
|
||||
/**
|
||||
* Whether or not to compute the hash. Must be set on the main thread before
|
||||
* setTarget is called.
|
||||
*/
|
||||
bool mSha256Enabled;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// State handled exclusively by the worker thread
|
||||
|
||||
|
@ -184,12 +156,6 @@ private:
|
|||
*/
|
||||
bool mActualTargetKeepPartial;
|
||||
|
||||
/**
|
||||
* Used to calculate the file hash. This keeps state across file renames and
|
||||
* is lazily initialized in ProcessStateChange.
|
||||
*/
|
||||
ScopedPK11Context mDigestContext;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Private methods
|
||||
|
||||
|
@ -271,8 +237,7 @@ private:
|
|||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// BackgroundFileSaverStreamListener. This class is instantiated by
|
||||
// nsExternalHelperAppService, DownloadCore.jsm, and possibly others.
|
||||
//// BackgroundFileSaverStreamListener
|
||||
|
||||
class BackgroundFileSaverStreamListener : public BackgroundFileSaver
|
||||
, public nsIStreamListener
|
||||
|
@ -323,31 +288,6 @@ private:
|
|||
nsresult NotifySuspendOrResume();
|
||||
};
|
||||
|
||||
// A wrapper around nsIOutputStream, so that we can compute hashes on the
|
||||
// stream without copying and without polluting pristine NSS code with XPCOM
|
||||
// interfaces.
|
||||
class DigestOutputStream : public nsNSSShutDownObject,
|
||||
public nsIOutputStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOUTPUTSTREAM
|
||||
// Constructor. Neither parameter may be null. The caller owns both.
|
||||
DigestOutputStream(nsIOutputStream* outputStream, PK11Context* aContext);
|
||||
~DigestOutputStream();
|
||||
|
||||
// We don't own any NSS objects here, so no need to clean up
|
||||
void virtualDestroyNSSReference() { }
|
||||
|
||||
private:
|
||||
// Calls to write are passed to this stream.
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
// Digest context used to compute the hash, owned by the caller.
|
||||
PK11Context* mDigestContext;
|
||||
|
||||
// Don't accidentally copy construct.
|
||||
DigestOutputStream(const DigestOutputStream& d);
|
||||
};
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -45,16 +45,6 @@ const TEST_FILE_NAME_1 = "test-backgroundfilesaver-1.txt";
|
|||
const TEST_FILE_NAME_2 = "test-backgroundfilesaver-2.txt";
|
||||
const TEST_FILE_NAME_3 = "test-backgroundfilesaver-3.txt";
|
||||
|
||||
// A map of test data length to the expected hash
|
||||
const EXPECTED_HASHES = {
|
||||
// SHA-256 hash of TEST_DATA_SHORT
|
||||
40 : "f37176b690e8744ee990a206c086cba54d1502aa2456c3b0c84ef6345d72a192",
|
||||
// SHA-256 hash of TEST_DATA_SHORT + TEST_DATA_SHORT
|
||||
80 : "780c0e91f50bb7ec922cc11e16859e6d5df283c0d9470f61772e3d79f41eeb58",
|
||||
// SHA-256 hash of a bunch of dashes
|
||||
16777216 : "03a0db69a30140f307587ee746a539247c181bafd85b85c8516a3533c7d9ea1d"
|
||||
};
|
||||
|
||||
const gTextDecoder = new TextDecoder();
|
||||
|
||||
// Generate a long string of data in a moderately fast way.
|
||||
|
@ -77,21 +67,6 @@ function getTempFile(aLeafName) {
|
|||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for converting a binary blob to its hex equivalent.
|
||||
*
|
||||
* @param str
|
||||
* String possibly containing non-printable chars.
|
||||
* @return A hex-encoded string.
|
||||
*/
|
||||
function toHex(str) {
|
||||
var hex = '';
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
hex += ('0' + str.charCodeAt(i).toString(16)).slice(-2);
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the given file contents are equal to the given string.
|
||||
*
|
||||
|
@ -323,7 +298,6 @@ add_task(function test_combinations()
|
|||
let saver = useStreamListener
|
||||
? new BackgroundFileSaverStreamListener()
|
||||
: new BackgroundFileSaverOutputStream();
|
||||
saver.enableSha256();
|
||||
let completionPromise = promiseSaverComplete(saver, onTargetChange);
|
||||
|
||||
// Start feeding the first chunk of data to the saver. In case we are using
|
||||
|
@ -366,10 +340,9 @@ add_task(function test_combinations()
|
|||
if (!cancelAtSomePoint) {
|
||||
// In this case, the file must exist.
|
||||
do_check_true(currentFile.exists());
|
||||
expectedContents = testData + testData;
|
||||
yield promiseVerifyContents(currentFile, expectedContents);
|
||||
do_check_eq(EXPECTED_HASHES[expectedContents.length],
|
||||
toHex(saver.sha256Hash));
|
||||
if (!cancelAtSomePoint) {
|
||||
yield promiseVerifyContents(currentFile, testData + testData);
|
||||
}
|
||||
currentFile.remove(false);
|
||||
|
||||
// If the target was really renamed, the old file should not exist.
|
||||
|
@ -406,7 +379,6 @@ add_task(function test_setTarget_after_close_stream()
|
|||
// where the file already exists.
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let saver = new BackgroundFileSaverOutputStream();
|
||||
saver.enableSha256();
|
||||
let completionPromise = promiseSaverComplete(saver);
|
||||
|
||||
// Copy some data to the output stream of the file saver. This data must
|
||||
|
@ -422,8 +394,6 @@ add_task(function test_setTarget_after_close_stream()
|
|||
|
||||
// Verify results.
|
||||
yield promiseVerifyContents(destFile, TEST_DATA_SHORT);
|
||||
do_check_eq(EXPECTED_HASHES[TEST_DATA_SHORT.length],
|
||||
toHex(saver.sha256Hash));
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
|
@ -468,29 +438,6 @@ add_task(function test_finish_only()
|
|||
yield completionPromise;
|
||||
});
|
||||
|
||||
add_task(function test_invalid_hash()
|
||||
{
|
||||
let saver = new BackgroundFileSaverStreamListener();
|
||||
// We shouldn't be able to get the hash if hashing hasn't been enabled
|
||||
try {
|
||||
let hash = saver.sha256Hash;
|
||||
throw "Shouldn't be able to get hash if hashing not enabled";
|
||||
} catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
|
||||
// Enable hashing, but don't feed any data to saver
|
||||
saver.enableSha256();
|
||||
let destFile = getTempFile(TEST_FILE_NAME_1);
|
||||
saver.setTarget(destFile, false);
|
||||
// We don't wait on promiseSaverComplete, so the hash getter can run before
|
||||
// or after onSaveComplete is called. However, the expected behavior is the
|
||||
// same in both cases since the hash is only valid when the save completes
|
||||
// successfully.
|
||||
saver.finish(Cr.NS_ERROR_FAILURE);
|
||||
try {
|
||||
let hash = saver.sha256Hash;
|
||||
throw "Shouldn't be able to get hash if save did not succeed";
|
||||
} catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
|
||||
});
|
||||
|
||||
add_task(function test_teardown()
|
||||
{
|
||||
gStillRunning = false;
|
||||
|
|
|
@ -124,13 +124,10 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPK11Context,
|
|||
mozilla::psm::PK11_DestroyContext_true)
|
||||
|
||||
/** A more convenient way of dealing with digests calculated into
|
||||
* stack-allocated buffers. NSS must be initialized on the main thread before
|
||||
* use, and the caller must ensure NSS isn't shut down, typically by
|
||||
* subclassing nsNSSShutDownObject, while Digest is in use.
|
||||
* stack-allocated buffers.
|
||||
*
|
||||
* Typical usage, for digesting a buffer in memory:
|
||||
*
|
||||
* nsCOMPtr<nsISupports> nssDummy = do_GetService("@mozilla.org/psm;1", &rv);
|
||||
* Digest digest;
|
||||
* nsresult rv = digest.DigestBuf(SEC_OID_SHA256, mybuffer, myBufferLen);
|
||||
* NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -147,7 +144,7 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPK11Context,
|
|||
* rv = MapSECStatus(PK11_DigestOp(digestContext, ...));
|
||||
* NS_ENSURE_SUCCESS(rv, rv);
|
||||
* }
|
||||
* rv = digest.End(SEC_OID_SHA1, digestContext);
|
||||
* rv = digestContext.End(SEC_OID_SHA1, digestContext);
|
||||
* NS_ENSURE_SUCCESS(rv, rv)
|
||||
*/
|
||||
class Digest
|
||||
|
|
Загрузка…
Ссылка в новой задаче