Bug 452390 Tracemonkey will crash if the compiler doesn't have FASTCALL r=danderson
[wine-gecko.git] / security / manager / ssl / src / nsKeygenThread.cpp
blob19d7844924f81dd3cdfcb4593986fdb7d686ae1d
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2001
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "pk11func.h"
40 #include "nsCOMPtr.h"
41 #include "nsProxiedService.h"
42 #include "nsThreadUtils.h"
43 #include "nsKeygenThread.h"
44 #include "nsIObserver.h"
45 #include "nsNSSShutDown.h"
47 NS_IMPL_THREADSAFE_ISUPPORTS1(nsKeygenThread, nsIKeygenThread)
50 nsKeygenThread::nsKeygenThread()
51 :mutex(nsnull),
52 iAmRunning(PR_FALSE),
53 keygenReady(PR_FALSE),
54 statusDialogClosed(PR_FALSE),
55 alreadyReceivedParams(PR_FALSE),
56 privateKey(nsnull),
57 publicKey(nsnull),
58 slot(nsnull),
59 keyGenMechanism(0),
60 params(nsnull),
61 isPerm(PR_FALSE),
62 isSensitive(PR_FALSE),
63 wincx(nsnull),
64 threadHandle(nsnull)
66 mutex = PR_NewLock();
69 nsKeygenThread::~nsKeygenThread()
71 if (mutex) {
72 PR_DestroyLock(mutex);
76 void nsKeygenThread::SetParams(
77 PK11SlotInfo *a_slot,
78 PRUint32 a_keyGenMechanism,
79 void *a_params,
80 PRBool a_isPerm,
81 PRBool a_isSensitive,
82 void *a_wincx )
84 nsNSSShutDownPreventionLock locker;
85 PR_Lock(mutex);
87 if (!alreadyReceivedParams) {
88 alreadyReceivedParams = PR_TRUE;
89 if (a_slot) {
90 slot = PK11_ReferenceSlot(a_slot);
92 else {
93 slot = nsnull;
95 keyGenMechanism = a_keyGenMechanism;
96 params = a_params;
97 isPerm = a_isPerm;
98 isSensitive = a_isSensitive;
99 wincx = a_wincx;
102 PR_Unlock(mutex);
105 nsresult nsKeygenThread::GetParams(
106 SECKEYPrivateKey **a_privateKey,
107 SECKEYPublicKey **a_publicKey)
109 if (!a_privateKey || !a_publicKey) {
110 return NS_ERROR_FAILURE;
113 nsresult rv;
115 PR_Lock(mutex);
117 // GetParams must not be called until thread creator called
118 // Join on this thread.
119 NS_ASSERTION(keygenReady, "logic error in nsKeygenThread::GetParams");
121 if (keygenReady) {
122 *a_privateKey = privateKey;
123 *a_publicKey = publicKey;
125 privateKey = 0;
126 publicKey = 0;
128 rv = NS_OK;
130 else {
131 rv = NS_ERROR_FAILURE;
134 PR_Unlock(mutex);
136 return rv;
139 static void PR_CALLBACK nsKeygenThreadRunner(void *arg)
141 nsKeygenThread *self = static_cast<nsKeygenThread *>(arg);
142 self->Run();
145 nsresult nsKeygenThread::StartKeyGeneration(nsIObserver* aObserver)
147 if (!mutex)
148 return NS_OK;
150 if (!aObserver)
151 return NS_OK;
153 nsCOMPtr<nsIObserver> obs;
154 NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD,
155 NS_GET_IID(nsIObserver),
156 aObserver,
157 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
158 getter_AddRefs(obs));
160 PR_Lock(mutex);
162 if (iAmRunning || keygenReady) {
163 PR_Unlock(mutex);
164 return NS_OK;
167 observer.swap(obs);
169 iAmRunning = PR_TRUE;
171 threadHandle = PR_CreateThread(PR_USER_THREAD, nsKeygenThreadRunner, static_cast<void*>(this),
172 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
174 // bool thread_started_ok = (threadHandle != nsnull);
175 // we might want to return "thread started ok" to caller in the future
176 NS_ASSERTION(threadHandle, "Could not create nsKeygenThreadRunner thread\n");
178 PR_Unlock(mutex);
180 return NS_OK;
183 nsresult nsKeygenThread::UserCanceled(PRBool *threadAlreadyClosedDialog)
185 if (!threadAlreadyClosedDialog)
186 return NS_OK;
188 *threadAlreadyClosedDialog = PR_FALSE;
190 if (!mutex)
191 return NS_OK;
193 PR_Lock(mutex);
195 if (keygenReady)
196 *threadAlreadyClosedDialog = statusDialogClosed;
198 // User somehow closed the dialog, but we will not cancel.
199 // Bad luck, we told him not do, and user still has to wait.
200 // However, we remember that it's closed and will not close
201 // it again to avoid problems.
202 statusDialogClosed = PR_TRUE;
204 PR_Unlock(mutex);
206 return NS_OK;
209 void nsKeygenThread::Run(void)
211 nsNSSShutDownPreventionLock locker;
212 PRBool canGenerate = PR_FALSE;
214 PR_Lock(mutex);
216 if (alreadyReceivedParams) {
217 canGenerate = PR_TRUE;
218 keygenReady = PR_FALSE;
221 PR_Unlock(mutex);
223 if (canGenerate)
224 privateKey = PK11_GenerateKeyPair(slot, keyGenMechanism,
225 params, &publicKey,
226 isPerm, isSensitive, wincx);
228 // This call gave us ownership over privateKey and publicKey.
229 // But as the params structure is owner by our caller,
230 // we effectively transferred ownership to the caller.
231 // As long as key generation can't be canceled, we don't need
232 // to care for cleaning this up.
234 nsCOMPtr<nsIObserver> obs;
235 PR_Lock(mutex);
237 keygenReady = PR_TRUE;
238 iAmRunning = PR_FALSE;
240 // forget our parameters
241 if (slot) {
242 PK11_FreeSlot(slot);
243 slot = 0;
245 keyGenMechanism = 0;
246 params = 0;
247 wincx = 0;
249 if (!statusDialogClosed)
250 obs = observer;
252 observer = nsnull;
254 PR_Unlock(mutex);
256 if (obs)
257 obs->Observe(nsnull, "keygen-finished", nsnull);
260 void nsKeygenThread::Join()
262 if (!threadHandle)
263 return;
265 PR_JoinThread(threadHandle);
266 threadHandle = nsnull;
268 return;