PageRenderTime 14ms CodeModel.GetById 1ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/security/manager/ssl/src/nsCertVerificationThread.cpp

http://github.com/zpao/v8monkey
C++ | 233 lines | 152 code | 43 blank | 38 comment | 18 complexity | 5a1e0c4187645a0ca923a39bcc14ed4a MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is mozilla.org code.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Red Hat, Inc.
 18 * Portions created by the Initial Developer are Copyright (C) 2006
 19 * the Initial Developer. All Rights Reserved.
 20 *
 21 * Contributor(s):
 22 *   Kai Engert <kengert@redhat.com>
 23 *
 24 * Alternatively, the contents of this file may be used under the terms of
 25 * either the GNU General Public License Version 2 or later (the "GPL"), or
 26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 27 * in which case the provisions of the GPL or the LGPL are applicable instead
 28 * of those above. If you wish to allow use of your version of this file only
 29 * under the terms of either the GPL or the LGPL, and not to allow others to
 30 * use your version of this file under the terms of the MPL, indicate your
 31 * decision by deleting the provisions above and replace them with the notice
 32 * and other provisions required by the GPL or the LGPL. If you do not delete
 33 * the provisions above, a recipient may use your version of this file under
 34 * the terms of any one of the MPL, the GPL or the LGPL.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37
 38#include "nsMemory.h"
 39#include "nsAutoPtr.h"
 40#include "nsCertVerificationThread.h"
 41#include "nsThreadUtils.h"
 42
 43using namespace mozilla;
 44
 45nsCertVerificationThread *nsCertVerificationThread::verification_thread_singleton;
 46
 47NS_IMPL_THREADSAFE_ISUPPORTS1(nsCertVerificationResult, nsICertVerificationResult)
 48
 49namespace {
 50class DispatchCertVerificationResult : public nsRunnable
 51{
 52public:
 53  DispatchCertVerificationResult(nsICertVerificationListener* aListener,
 54                                 nsIX509Cert3* aCert,
 55                                 nsICertVerificationResult* aResult)
 56    : mListener(aListener)
 57    , mCert(aCert)
 58    , mResult(aResult)
 59  { }
 60
 61  NS_IMETHOD Run() {
 62    mListener->Notify(mCert, mResult);
 63    return NS_OK;
 64  }
 65
 66private:
 67  nsCOMPtr<nsICertVerificationListener> mListener;
 68  nsCOMPtr<nsIX509Cert3> mCert;
 69  nsCOMPtr<nsICertVerificationResult> mResult;
 70};
 71} // anonymous namespace
 72
 73void nsCertVerificationJob::Run()
 74{
 75  if (!mListener || !mCert)
 76    return;
 77
 78  PRUint32 verified;
 79  PRUint32 count;
 80  PRUnichar **usages;
 81
 82  nsCOMPtr<nsICertVerificationResult> ires;
 83  nsRefPtr<nsCertVerificationResult> vres = new nsCertVerificationResult;
 84  if (vres)
 85  {
 86    nsresult rv = mCert->GetUsagesArray(false, // do not ignore OCSP
 87                                        &verified,
 88                                        &count,
 89                                        &usages);
 90    vres->mRV = rv;
 91    if (NS_SUCCEEDED(rv))
 92    {
 93      vres->mVerified = verified;
 94      vres->mCount = count;
 95      vres->mUsages = usages;
 96    }
 97
 98    ires = vres;
 99  }
100  
101  nsCOMPtr<nsIX509Cert3> c3 = do_QueryInterface(mCert);
102  nsCOMPtr<nsIRunnable> r = new DispatchCertVerificationResult(mListener, c3, ires);
103  NS_DispatchToMainThread(r);
104}
105
106void nsSMimeVerificationJob::Run()
107{
108  if (!mMessage || !mListener)
109    return;
110  
111  nsresult rv;
112  
113  if (digest_data)
114    rv = mMessage->VerifyDetachedSignature(digest_data, digest_len);
115  else
116    rv = mMessage->VerifySignature();
117  
118  nsCOMPtr<nsICMSMessage2> m2 = do_QueryInterface(mMessage);
119  mListener->Notify(m2, rv);
120}
121
122nsCertVerificationThread::nsCertVerificationThread()
123: mJobQ(nsnull)
124{
125  NS_ASSERTION(!verification_thread_singleton, 
126               "nsCertVerificationThread is a singleton, caller attempts"
127               " to create another instance!");
128  
129  verification_thread_singleton = this;
130}
131
132nsCertVerificationThread::~nsCertVerificationThread()
133{
134  verification_thread_singleton = nsnull;
135}
136
137nsresult nsCertVerificationThread::addJob(nsBaseVerificationJob *aJob)
138{
139  if (!aJob || !verification_thread_singleton)
140    return NS_ERROR_FAILURE;
141  
142  if (!verification_thread_singleton->mThreadHandle)
143    return NS_ERROR_OUT_OF_MEMORY;
144
145  MutexAutoLock threadLock(verification_thread_singleton->mMutex);
146
147  verification_thread_singleton->mJobQ.Push(aJob);
148  verification_thread_singleton->mCond.NotifyAll();
149  
150  return NS_OK;
151}
152
153void nsCertVerificationThread::Run(void)
154{
155  while (true) {
156
157    nsBaseVerificationJob *job = nsnull;
158
159    {
160      MutexAutoLock threadLock(verification_thread_singleton->mMutex);
161
162      while (!exitRequested(threadLock) &&
163             0 == verification_thread_singleton->mJobQ.GetSize()) {
164        // no work to do ? let's wait a moment
165
166        mCond.Wait();
167      }
168      
169      if (exitRequested(threadLock))
170        break;
171      
172      job = static_cast<nsBaseVerificationJob*>(mJobQ.PopFront());
173    }
174
175    if (job)
176    {
177      job->Run();
178      delete job;
179    }
180  }
181  
182  {
183    MutexAutoLock threadLock(verification_thread_singleton->mMutex);
184
185    while (verification_thread_singleton->mJobQ.GetSize()) {
186      nsCertVerificationJob *job = 
187        static_cast<nsCertVerificationJob*>(mJobQ.PopFront());
188      delete job;
189    }
190    postStoppedEventToMainThread(threadLock);
191  }
192}
193
194nsCertVerificationResult::nsCertVerificationResult()
195: mRV(0),
196  mVerified(0),
197  mCount(0),
198  mUsages(0)
199{
200}
201
202nsCertVerificationResult::~nsCertVerificationResult()
203{
204  if (mUsages)
205  {
206    NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mUsages);
207  }
208}
209
210NS_IMETHODIMP
211nsCertVerificationResult::GetUsagesArrayResult(PRUint32 *aVerified,
212                                               PRUint32 *aCount,
213                                               PRUnichar ***aUsages)
214{
215  if (NS_FAILED(mRV))
216    return mRV;
217  
218  // transfer ownership
219  
220  *aVerified = mVerified;
221  *aCount = mCount;
222  *aUsages = mUsages;
223  
224  mVerified = 0;
225  mCount = 0;
226  mUsages = 0;
227  
228  nsresult rv = mRV;
229  
230  mRV = NS_ERROR_FAILURE; // this object works only once...
231  
232  return rv;
233}