Bug 572417 - Release mouse capture in flash subclass after mouse events get delivered...
[mozilla-central.git] / xpcom / base / nsUUIDGenerator.cpp
bloba9f74fd45cd335839f34b197778a5a23a579e80f
1 /* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * mozilla.org
19 * Portions created by the Initial Developer are Copyright (C) 2005
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Vladimir Vukicevic <vladimir@pobox.com> (original author)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or 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 #if defined(XP_WIN)
40 #include <windows.h>
41 #include <objbase.h>
42 #elif defined(XP_MACOSX)
43 #include <CoreFoundation/CoreFoundation.h>
44 #else
45 #include <stdlib.h>
46 #include "prrng.h"
47 #endif
49 #include "nsMemory.h"
51 #include "nsAutoLock.h"
53 #include "nsUUIDGenerator.h"
55 NS_IMPL_THREADSAFE_ISUPPORTS1(nsUUIDGenerator, nsIUUIDGenerator)
57 nsUUIDGenerator::nsUUIDGenerator()
58 : mLock(nsnull)
62 nsUUIDGenerator::~nsUUIDGenerator()
64 if (mLock) {
65 PR_DestroyLock(mLock);
69 nsresult
70 nsUUIDGenerator::Init()
72 mLock = PR_NewLock();
74 NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
76 // We're a service, so we're guaranteed that Init() is not going
77 // to be reentered while we're inside Init().
79 #if !defined(XP_WIN) && !defined(XP_MACOSX) && !defined(ANDROID)
80 /* initialize random number generator using NSPR random noise */
81 unsigned int seed;
83 PRSize bytes = 0;
84 while (bytes < sizeof(seed)) {
85 PRSize nbytes = PR_GetRandomNoise(((unsigned char *)&seed)+bytes,
86 sizeof(seed)-bytes);
87 if (nbytes == 0) {
88 return NS_ERROR_FAILURE;
90 bytes += nbytes;
93 /* Initialize a new RNG state, and immediately switch
94 * back to the previous one -- we want to use mState
95 * only for our own calls to random().
97 mSavedState = initstate(seed, mState, sizeof(mState));
98 setstate(mSavedState);
100 mRBytes = 4;
101 #ifdef RAND_MAX
102 if ((unsigned long) RAND_MAX < (unsigned long)0xffffffff)
103 mRBytes = 3;
104 if ((unsigned long) RAND_MAX < (unsigned long)0x00ffffff)
105 mRBytes = 2;
106 if ((unsigned long) RAND_MAX < (unsigned long)0x0000ffff)
107 mRBytes = 1;
108 if ((unsigned long) RAND_MAX < (unsigned long)0x000000ff)
109 return NS_ERROR_FAILURE;
110 #endif
112 #endif /* non XP_WIN and non XP_MACOSX */
114 return NS_OK;
117 NS_IMETHODIMP
118 nsUUIDGenerator::GenerateUUID(nsID** ret)
120 nsID *id = static_cast<nsID*>(NS_Alloc(sizeof(nsID)));
121 if (id == nsnull)
122 return NS_ERROR_OUT_OF_MEMORY;
124 nsresult rv = GenerateUUIDInPlace(id);
125 if (NS_FAILED(rv)) {
126 NS_Free(id);
127 return rv;
130 *ret = id;
131 return rv;
134 NS_IMETHODIMP
135 nsUUIDGenerator::GenerateUUIDInPlace(nsID* id)
137 // The various code in this method is probably not threadsafe, so lock
138 // across the whole method.
139 nsAutoLock lock(mLock);
141 #if defined(WINCE)
142 // WINCE only has CoCreateGuid if DCOM support is compiled into the BSP;
143 // there's usually very little reason for DCOM to be present!
145 if (!CeGenRandom(sizeof(nsID), (BYTE*) id))
146 return NS_ERROR_FAILURE;
148 /* Put in the version */
149 id->m2 &= 0x0fff;
150 id->m2 |= 0x4000;
152 /* Put in the variant */
153 id->m3[0] &= 0x3f;
154 id->m3[0] |= 0x80;
156 #elif defined(XP_WIN)
157 HRESULT hr = CoCreateGuid((GUID*)id);
158 if (NS_FAILED(hr))
159 return NS_ERROR_FAILURE;
160 #elif defined(XP_MACOSX)
161 CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
162 if (!uuid)
163 return NS_ERROR_FAILURE;
165 CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
166 memcpy(id, &bytes, sizeof(nsID));
168 CFRelease(uuid);
169 #else /* not windows or OS X; generate randomness using random(). */
170 /* XXX we should be saving the return of setstate here and switching
171 * back to it; instead, we use the value returned when we called
172 * initstate, since older glibc's have broken setstate() return values
174 #ifndef ANDROID
175 setstate(mState);
176 #endif
178 PRSize bytesLeft = sizeof(nsID);
179 while (bytesLeft > 0) {
180 #ifdef ANDROID
181 long rval = arc4random();
182 const int mRBytes = 4;
183 #else
184 long rval = random();
185 #endif
188 PRUint8 *src = (PRUint8*)&rval;
189 // We want to grab the mRBytes least significant bytes of rval, since
190 // mRBytes less than sizeof(rval) means the high bytes are 0.
191 #ifdef IS_BIG_ENDIAN
192 src += sizeof(rval) - mRBytes;
193 #endif
194 PRUint8 *dst = ((PRUint8*) id) + (sizeof(nsID) - bytesLeft);
195 PRSize toWrite = (bytesLeft < mRBytes ? bytesLeft : mRBytes);
196 for (PRSize i = 0; i < toWrite; i++)
197 dst[i] = src[i];
199 bytesLeft -= toWrite;
202 /* Put in the version */
203 id->m2 &= 0x0fff;
204 id->m2 |= 0x4000;
206 /* Put in the variant */
207 id->m3[0] &= 0x3f;
208 id->m3[0] |= 0x80;
210 #ifndef ANDROID
211 /* Restore the previous RNG state */
212 setstate(mSavedState);
213 #endif
214 #endif
216 return NS_OK;