Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "CryptoTask.h"
8 : #include "nsNSSComponent.h"
9 :
10 : namespace mozilla {
11 :
12 0 : CryptoTask::~CryptoTask()
13 : {
14 0 : MOZ_ASSERT(mReleasedNSSResources);
15 :
16 0 : nsNSSShutDownPreventionLock lock;
17 0 : if (!isAlreadyShutDown()) {
18 0 : shutdown(ShutdownCalledFrom::Object);
19 : }
20 0 : }
21 :
22 : nsresult
23 0 : CryptoTask::Dispatch(const nsACString& taskThreadName)
24 : {
25 0 : MOZ_ASSERT(taskThreadName.Length() <= 15);
26 :
27 : // Ensure that NSS is initialized, since presumably CalculateResult
28 : // will use NSS functions
29 0 : if (!EnsureNSSInitializedChromeOrContent()) {
30 0 : return NS_ERROR_FAILURE;
31 : }
32 :
33 : // Can't add 'this' as the event to run, since mThread may not be set yet
34 0 : nsresult rv = NS_NewNamedThread(taskThreadName, getter_AddRefs(mThread),
35 : nullptr,
36 0 : nsIThreadManager::DEFAULT_STACK_SIZE);
37 0 : if (NS_FAILED(rv)) {
38 0 : return rv;
39 : }
40 :
41 : // Note: event must not null out mThread!
42 0 : return mThread->Dispatch(this, NS_DISPATCH_NORMAL);
43 : }
44 :
45 : NS_IMETHODIMP
46 0 : CryptoTask::Run()
47 : {
48 0 : if (!NS_IsMainThread()) {
49 0 : nsNSSShutDownPreventionLock locker;
50 0 : if (isAlreadyShutDown()) {
51 0 : mRv = NS_ERROR_NOT_AVAILABLE;
52 : } else {
53 0 : mRv = CalculateResult();
54 : }
55 0 : NS_DispatchToMainThread(this);
56 : } else {
57 : // back on the main thread
58 :
59 : // call ReleaseNSSResources now, before calling CallCallback, so that
60 : // CryptoTasks have consistent behavior regardless of whether NSS is shut
61 : // down between CalculateResult being called and CallCallback being called.
62 0 : if (!mReleasedNSSResources) {
63 0 : mReleasedNSSResources = true;
64 0 : ReleaseNSSResources();
65 : }
66 :
67 0 : CallCallback(mRv);
68 :
69 : // Not all uses of CryptoTask use a transient thread
70 0 : if (mThread) {
71 : // Don't leak threads!
72 0 : mThread->Shutdown(); // can't Shutdown from the thread itself, darn
73 : // Don't null out mThread!
74 : // See bug 999104. We must hold a ref to the thread across Dispatch()
75 : // since the internal mThread ref could be released while processing
76 : // the Dispatch(), and Dispatch/PutEvent itself doesn't hold a ref; it
77 : // assumes the caller does.
78 : }
79 : }
80 :
81 0 : return NS_OK;
82 : }
83 :
84 : void
85 0 : CryptoTask::virtualDestroyNSSReference()
86 : {
87 0 : MOZ_ASSERT(NS_IsMainThread(),
88 : "virtualDestroyNSSReference called off the main thread");
89 0 : if (!mReleasedNSSResources) {
90 0 : mReleasedNSSResources = true;
91 0 : ReleaseNSSResources();
92 : }
93 0 : }
94 :
95 : } // namespace mozilla
|