Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsCertVerificationThread.h"
6 #include "nsThreadUtils.h"
7 #include "nsProxyRelease.h"
9 using namespace mozilla;
11 nsCertVerificationThread *nsCertVerificationThread::verification_thread_singleton;
13 NS_IMPL_ISUPPORTS(nsCertVerificationResult, nsICertVerificationResult)
15 namespace {
16 class DispatchCertVerificationResult : public nsRunnable
17 {
18 public:
19 DispatchCertVerificationResult(const nsMainThreadPtrHandle<nsICertVerificationListener>& aListener,
20 nsIX509Cert3* aCert,
21 nsICertVerificationResult* aResult)
22 : mListener(aListener)
23 , mCert(aCert)
24 , mResult(aResult)
25 { }
27 NS_IMETHOD Run() {
28 mListener->Notify(mCert, mResult);
29 return NS_OK;
30 }
32 private:
33 nsMainThreadPtrHandle<nsICertVerificationListener> mListener;
34 nsCOMPtr<nsIX509Cert3> mCert;
35 nsCOMPtr<nsICertVerificationResult> mResult;
36 };
37 } // anonymous namespace
39 void nsCertVerificationJob::Run()
40 {
41 if (!mListener || !mCert)
42 return;
44 uint32_t verified;
45 uint32_t count;
46 char16_t **usages;
48 nsCOMPtr<nsICertVerificationResult> ires;
49 RefPtr<nsCertVerificationResult> vres(new nsCertVerificationResult);
50 if (vres)
51 {
52 nsresult rv = mCert->GetUsagesArray(false, // do not ignore OCSP
53 &verified,
54 &count,
55 &usages);
56 vres->mRV = rv;
57 if (NS_SUCCEEDED(rv))
58 {
59 vres->mVerified = verified;
60 vres->mCount = count;
61 vres->mUsages = usages;
62 }
64 ires = vres;
65 }
67 nsCOMPtr<nsIX509Cert3> c3 = do_QueryInterface(mCert);
68 nsCOMPtr<nsIRunnable> r = new DispatchCertVerificationResult(mListener, c3, ires);
69 NS_DispatchToMainThread(r);
70 }
72 void nsSMimeVerificationJob::Run()
73 {
74 if (!mMessage || !mListener)
75 return;
77 nsresult rv;
79 if (digest_data)
80 rv = mMessage->VerifyDetachedSignature(digest_data, digest_len);
81 else
82 rv = mMessage->VerifySignature();
84 nsCOMPtr<nsICMSMessage2> m2 = do_QueryInterface(mMessage);
85 mListener->Notify(m2, rv);
86 }
88 nsCertVerificationThread::nsCertVerificationThread()
89 : mJobQ(nullptr)
90 {
91 NS_ASSERTION(!verification_thread_singleton,
92 "nsCertVerificationThread is a singleton, caller attempts"
93 " to create another instance!");
95 verification_thread_singleton = this;
96 }
98 nsCertVerificationThread::~nsCertVerificationThread()
99 {
100 verification_thread_singleton = nullptr;
101 }
103 nsresult nsCertVerificationThread::addJob(nsBaseVerificationJob *aJob)
104 {
105 if (!aJob || !verification_thread_singleton)
106 return NS_ERROR_FAILURE;
108 if (!verification_thread_singleton->mThreadHandle)
109 return NS_ERROR_OUT_OF_MEMORY;
111 MutexAutoLock threadLock(verification_thread_singleton->mMutex);
113 verification_thread_singleton->mJobQ.Push(aJob);
114 verification_thread_singleton->mCond.NotifyAll();
116 return NS_OK;
117 }
119 void nsCertVerificationThread::Run(void)
120 {
121 while (true) {
123 nsBaseVerificationJob *job = nullptr;
125 {
126 MutexAutoLock threadLock(verification_thread_singleton->mMutex);
128 while (!exitRequested(threadLock) &&
129 0 == verification_thread_singleton->mJobQ.GetSize()) {
130 // no work to do ? let's wait a moment
132 mCond.Wait();
133 }
135 if (exitRequested(threadLock))
136 break;
138 job = static_cast<nsBaseVerificationJob*>(mJobQ.PopFront());
139 }
141 if (job)
142 {
143 job->Run();
144 delete job;
145 }
146 }
148 {
149 MutexAutoLock threadLock(verification_thread_singleton->mMutex);
151 while (verification_thread_singleton->mJobQ.GetSize()) {
152 nsCertVerificationJob *job =
153 static_cast<nsCertVerificationJob*>(mJobQ.PopFront());
154 delete job;
155 }
156 postStoppedEventToMainThread(threadLock);
157 }
158 }
160 nsCertVerificationResult::nsCertVerificationResult()
161 : mRV(NS_OK),
162 mVerified(0),
163 mCount(0),
164 mUsages(0)
165 {
166 }
168 nsCertVerificationResult::~nsCertVerificationResult()
169 {
170 if (mUsages)
171 {
172 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mUsages);
173 }
174 }
176 NS_IMETHODIMP
177 nsCertVerificationResult::GetUsagesArrayResult(uint32_t *aVerified,
178 uint32_t *aCount,
179 char16_t ***aUsages)
180 {
181 if (NS_FAILED(mRV))
182 return mRV;
184 // transfer ownership
186 *aVerified = mVerified;
187 *aCount = mCount;
188 *aUsages = mUsages;
190 mVerified = 0;
191 mCount = 0;
192 mUsages = 0;
194 nsresult rv = mRV;
196 mRV = NS_ERROR_FAILURE; // this object works only once...
198 return rv;
199 }