LCOV - code coverage report
Current view: directory - xpcom/base - nsUUIDGenerator.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 47 43 91.5 %
Date: 2012-06-02 Functions: 8 8 100.0 %

       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
       4                 :  *
       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/
       9                 :  *
      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.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      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.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Vladimir Vukicevic <vladimir@pobox.com> (original author)
      24                 :  *
      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.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      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
      48                 : 
      49                 : #include "nsMemory.h"
      50                 : 
      51                 : #include "nsUUIDGenerator.h"
      52                 : 
      53                 : using namespace mozilla;
      54                 : 
      55           32073 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsUUIDGenerator, nsIUUIDGenerator)
      56                 : 
      57            1404 : nsUUIDGenerator::nsUUIDGenerator()
      58            1404 :     : mLock("nsUUIDGenerator.mLock")
      59                 : {
      60            1404 : }
      61                 : 
      62            1404 : nsUUIDGenerator::~nsUUIDGenerator()
      63                 : {
      64            1404 : }
      65                 : 
      66                 : nsresult
      67            1404 : nsUUIDGenerator::Init()
      68                 : {
      69                 :     // We're a service, so we're guaranteed that Init() is not going
      70                 :     // to be reentered while we're inside Init().
      71                 :     
      72                 : #if !defined(XP_WIN) && !defined(XP_MACOSX) && !defined(ANDROID)
      73                 :     /* initialize random number generator using NSPR random noise */
      74                 :     unsigned int seed;
      75                 : 
      76            1404 :     PRSize bytes = 0;
      77            4212 :     while (bytes < sizeof(seed)) {
      78            1404 :         PRSize nbytes = PR_GetRandomNoise(((unsigned char *)&seed)+bytes,
      79            2808 :                                           sizeof(seed)-bytes);
      80            1404 :         if (nbytes == 0) {
      81               0 :             return NS_ERROR_FAILURE;
      82                 :         }
      83            1404 :         bytes += nbytes;
      84                 :     }
      85                 : 
      86                 :     /* Initialize a new RNG state, and immediately switch
      87                 :      * back to the previous one -- we want to use mState
      88                 :      * only for our own calls to random().
      89                 :      */
      90            1404 :     mSavedState = initstate(seed, mState, sizeof(mState));
      91            1404 :     setstate(mSavedState);
      92                 : 
      93            1404 :     mRBytes = 4;
      94                 : #ifdef RAND_MAX
      95                 :     if ((unsigned long) RAND_MAX < (unsigned long)0xffffffff)
      96            1404 :         mRBytes = 3;
      97                 :     if ((unsigned long) RAND_MAX < (unsigned long)0x00ffffff)
      98                 :         mRBytes = 2;
      99                 :     if ((unsigned long) RAND_MAX < (unsigned long)0x0000ffff)
     100                 :         mRBytes = 1;
     101                 :     if ((unsigned long) RAND_MAX < (unsigned long)0x000000ff)
     102                 :         return NS_ERROR_FAILURE;
     103                 : #endif
     104                 : 
     105                 : #endif /* non XP_WIN and non XP_MACOSX */
     106                 : 
     107            1404 :     return NS_OK;
     108                 : }
     109                 : 
     110                 : NS_IMETHODIMP
     111            1395 : nsUUIDGenerator::GenerateUUID(nsID** ret)
     112                 : {
     113            1395 :     nsID *id = static_cast<nsID*>(NS_Alloc(sizeof(nsID)));
     114            1395 :     if (id == nsnull)
     115               0 :         return NS_ERROR_OUT_OF_MEMORY;
     116                 : 
     117            1395 :     nsresult rv = GenerateUUIDInPlace(id);
     118            1395 :     if (NS_FAILED(rv)) {
     119               0 :         NS_Free(id);
     120               0 :         return rv;
     121                 :     }
     122                 : 
     123            1395 :     *ret = id;
     124            1395 :     return rv;
     125                 : }
     126                 : 
     127                 : NS_IMETHODIMP
     128            5477 : nsUUIDGenerator::GenerateUUIDInPlace(nsID* id)
     129                 : {
     130                 :     // The various code in this method is probably not threadsafe, so lock
     131                 :     // across the whole method.
     132           10954 :     MutexAutoLock lock(mLock);
     133                 : 
     134                 : #if defined(XP_WIN)
     135                 :     HRESULT hr = CoCreateGuid((GUID*)id);
     136                 :     if (NS_FAILED(hr))
     137                 :         return NS_ERROR_FAILURE;
     138                 : #elif defined(XP_MACOSX)
     139                 :     CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
     140                 :     if (!uuid)
     141                 :         return NS_ERROR_FAILURE;
     142                 : 
     143                 :     CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
     144                 :     memcpy(id, &bytes, sizeof(nsID));
     145                 : 
     146                 :     CFRelease(uuid);
     147                 : #else /* not windows or OS X; generate randomness using random(). */
     148                 :     /* XXX we should be saving the return of setstate here and switching
     149                 :      * back to it; instead, we use the value returned when we called
     150                 :      * initstate, since older glibc's have broken setstate() return values
     151                 :      */
     152                 : #ifndef ANDROID
     153            5477 :     setstate(mState);
     154                 : #endif
     155                 : 
     156            5477 :     PRSize bytesLeft = sizeof(nsID);
     157           43816 :     while (bytesLeft > 0) {
     158                 : #ifdef ANDROID
     159                 :         long rval = arc4random();
     160                 :         const int mRBytes = 4;
     161                 : #else
     162           32862 :         long rval = random();
     163                 : #endif
     164                 : 
     165                 : 
     166           32862 :         PRUint8 *src = (PRUint8*)&rval;
     167                 :         // We want to grab the mRBytes least significant bytes of rval, since
     168                 :         // mRBytes less than sizeof(rval) means the high bytes are 0.
     169                 : #ifdef IS_BIG_ENDIAN
     170                 :         src += sizeof(rval) - mRBytes;
     171                 : #endif
     172           32862 :         PRUint8 *dst = ((PRUint8*) id) + (sizeof(nsID) - bytesLeft);
     173           32862 :         PRSize toWrite = (bytesLeft < mRBytes ? bytesLeft : mRBytes);
     174          120494 :         for (PRSize i = 0; i < toWrite; i++)
     175           87632 :             dst[i] = src[i];
     176                 : 
     177           32862 :         bytesLeft -= toWrite;
     178                 :     }
     179                 : 
     180                 :     /* Put in the version */
     181            5477 :     id->m2 &= 0x0fff;
     182            5477 :     id->m2 |= 0x4000;
     183                 : 
     184                 :     /* Put in the variant */
     185            5477 :     id->m3[0] &= 0x3f;
     186            5477 :     id->m3[0] |= 0x80;
     187                 : 
     188                 : #ifndef ANDROID
     189                 :     /* Restore the previous RNG state */
     190            5477 :     setstate(mSavedState);
     191                 : #endif
     192                 : #endif
     193                 : 
     194            5477 :     return NS_OK;
     195                 : }

Generated by: LCOV version 1.7