LCOV - code coverage report
Current view: directory - security/manager/ssl/src - nsNSSShutDown.h (source / functions) Found Hit Coverage
Test: app.info Lines: 32 29 90.6 %
Date: 2012-06-02 Functions: 11 8 72.7 %

       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 Communicator.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Netscape Communications Corporation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2002
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Kai Engert <kaie@netscape.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                 : #ifndef _INC_NSSShutDown_H
      39                 : #define _INC_NSSShutDown_H
      40                 : 
      41                 : #include "nscore.h"
      42                 : #include "nspr.h"
      43                 : #include "pldhash.h"
      44                 : #include "mozilla/CondVar.h"
      45                 : #include "mozilla/Mutex.h"
      46                 : 
      47                 : class nsNSSShutDownObject;
      48                 : class nsOnPK11LogoutCancelObject;
      49                 : 
      50                 : // Singleton, owner by nsNSSShutDownList
      51                 : class nsNSSActivityState
      52                 : {
      53                 : public:
      54                 :   nsNSSActivityState();
      55                 :   ~nsNSSActivityState();
      56                 : 
      57                 :   // Call enter/leave when PSM enters a scope during which
      58                 :   // shutting down NSS is prohibited.
      59                 :   void enter();
      60                 :   void leave();
      61                 :   
      62                 :   // Call enter/leave when PSM is about to show a UI
      63                 :   // while still holding resources.
      64                 :   void enterBlockingUIState();
      65                 :   void leaveBlockingUIState();
      66                 :   
      67                 :   // Is the activity aware of any blocking PSM UI currently shown?
      68                 :   bool isBlockingUIActive();
      69                 : 
      70                 :   // Is it forbidden to bring up an UI while holding resources?
      71                 :   bool isUIForbidden();
      72                 :   
      73                 :   // Check whether setting the current thread restriction is possible.
      74                 :   // If it is possible, and the "do_it_for_real" flag is used,
      75                 :   // the state tracking will have ensured that we will stay in this state.
      76                 :   // As of writing, this includes forbidding PSM UI.
      77                 :   enum RealOrTesting {test_only, do_it_for_real};
      78                 :   bool ifPossibleDisallowUI(RealOrTesting rot);
      79                 : 
      80                 :   // Notify the state tracking that going to the restricted state is
      81                 :   // no longer planned.
      82                 :   // As of writing, this includes clearing the "PSM UI forbidden" flag.
      83                 :   void allowUI();
      84                 : 
      85                 :   // If currently no UI is shown, wait for all activity to stop,
      86                 :   // and block any other thread on entering relevant PSM code.
      87                 :   PRStatus restrictActivityToCurrentThread();
      88                 :   
      89                 :   // Go back to normal state.
      90                 :   void releaseCurrentThreadActivityRestriction();
      91                 : 
      92                 : private:
      93                 :   // The lock protecting all our member variables.
      94                 :   mozilla::Mutex mNSSActivityStateLock;
      95                 : 
      96                 :   // The activity variable, bound to our lock,
      97                 :   // used either to signal the activity counter reaches zero,
      98                 :   // or a thread restriction has been released.
      99                 :   mozilla::CondVar mNSSActivityChanged;
     100                 : 
     101                 :   // The number of active scopes holding resources.
     102                 :   int mNSSActivityCounter;
     103                 : 
     104                 :   // The number of scopes holding resources while blocked
     105                 :   // showing an UI.
     106                 :   int mBlockingUICounter;
     107                 : 
     108                 :   // Whether bringing up UI is currently forbidden
     109                 :   bool mIsUIForbidden;
     110                 : 
     111                 :   // nsnull means "no restriction"
     112                 :   // if != nsnull, activity is only allowed on that thread
     113                 :   PRThread* mNSSRestrictedThread;
     114                 : };
     115                 : 
     116                 : // Helper class that automatically enters/leaves the global activity state
     117                 : class nsNSSShutDownPreventionLock
     118                 : {
     119                 : public:
     120                 :   nsNSSShutDownPreventionLock();
     121                 :   ~nsNSSShutDownPreventionLock();
     122                 : };
     123                 : 
     124                 : // Helper class that automatically enters/leaves the global UI tracking
     125                 : class nsPSMUITracker
     126                 : {
     127                 : public:
     128                 :   nsPSMUITracker();
     129                 :   ~nsPSMUITracker();
     130                 :   
     131                 :   bool isUIForbidden();
     132                 : };
     133                 : 
     134                 : // Singleton, used by nsNSSComponent to track the list of PSM objects,
     135                 : // which hold NSS resources and support the "early cleanup mechanism".
     136                 : class nsNSSShutDownList
     137                 : {
     138                 : public:
     139                 :   ~nsNSSShutDownList();
     140                 : 
     141                 :   static nsNSSShutDownList *construct();
     142                 :   
     143                 :   // track instances that support early cleanup
     144                 :   static void remember(nsNSSShutDownObject *o);
     145                 :   static void forget(nsNSSShutDownObject *o);
     146                 : 
     147                 :   // track instances that would like notification when
     148                 :   // a PK11 logout operation is performed.
     149                 :   static void remember(nsOnPK11LogoutCancelObject *o);
     150                 :   static void forget(nsOnPK11LogoutCancelObject *o);
     151                 : 
     152                 :   // track the creation and destruction of SSL sockets
     153                 :   // performed by clients using PSM services
     154                 :   static void trackSSLSocketCreate();
     155                 :   static void trackSSLSocketClose();
     156                 :   static bool areSSLSocketsActive();
     157                 :   
     158                 :   // Are we able to do the early cleanup?
     159                 :   // Returns failure if at the current time "early cleanup" is not possible.
     160                 :   bool isUIActive();
     161                 : 
     162                 :   // If possible to do "early cleanup" at the current time, remember that we want to
     163                 :   // do it, and disallow actions that would change the possibility.
     164                 :   bool ifPossibleDisallowUI();
     165                 : 
     166                 :   // Notify that it is no longer planned to do the "early cleanup".
     167                 :   void allowUI();
     168                 :   
     169                 :   // Do the "early cleanup", if possible.
     170                 :   nsresult evaporateAllNSSResources();
     171                 : 
     172                 :   // PSM has been asked to log out of a token.
     173                 :   // Notify all registered instances that want to react to that event.
     174                 :   nsresult doPK11Logout();
     175                 :   
     176          182410 :   static nsNSSActivityState *getActivityState()
     177                 :   {
     178          182410 :     return singleton ? &singleton->mActivityState : nsnull;
     179                 :   }
     180                 :   
     181                 : private:
     182                 :   nsNSSShutDownList();
     183                 :   static PLDHashOperator PR_CALLBACK
     184                 :   evaporateAllNSSResourcesHelper(PLDHashTable *table, PLDHashEntryHdr *hdr,
     185                 :                                                         PRUint32 number, void *arg);
     186                 : 
     187                 :   static PLDHashOperator PR_CALLBACK
     188                 :   doPK11LogoutHelper(PLDHashTable *table, PLDHashEntryHdr *hdr,
     189                 :                                                     PRUint32 number, void *arg);
     190                 : protected:
     191                 :   mozilla::Mutex mListLock;
     192                 :   static nsNSSShutDownList *singleton;
     193                 :   PLDHashTable mObjects;
     194                 :   PRUint32 mActiveSSLSockets;
     195                 :   PLDHashTable mPK11LogoutCancelObjects;
     196                 :   nsNSSActivityState mActivityState;
     197                 : };
     198                 : 
     199                 : /*
     200                 :   A class deriving from nsNSSShutDownObject will have its instances
     201                 :   automatically tracked in a list. However, it must follow some rules
     202                 :   to assure correct behaviour.
     203                 :   
     204                 :   The tricky part is that it is not possible to call virtual
     205                 :   functions from a destructor.
     206                 :   
     207                 :   The deriving class must override virtualDestroyNSSReference().
     208                 :   Within this function, it should clean up all resources held to NSS.
     209                 :   The function will be called by the global list, if it is time to
     210                 :   shut down NSS before all references have been freed.
     211                 : 
     212                 :   The same code that goes into virtualDestroyNSSReference must
     213                 :   also be called from the destructor of the deriving class,
     214                 :   which is the standard cleanup (not called from the tracking list).
     215                 : 
     216                 :   Because of that duplication, it is suggested to implement a
     217                 :   function destructorSafeDestroyNSSReference() in the deriving
     218                 :   class, and make the implementation of virtualDestroyNSSReference()
     219                 :   call destructorSafeDestroyNSSReference().
     220                 : 
     221                 :   The destructor of the derived class should call 
     222                 :   destructorSafeDestroyNSSReference() and afterwards call
     223                 :   shutdown(calledFromObject), in order to deregister with the
     224                 :   tracking list, to ensure no additional attempt to free the resources
     225                 :   will be made.
     226                 :   
     227                 :   Function destructorSafeDestroyNSSReference() must
     228                 :   also ensure, that NSS resources have not been freed already.
     229                 :   To achieve this, the deriving class should call 
     230                 :   isAlreadyShutDown() to check.
     231                 :   
     232                 :   It is important that you make your implementation
     233                 :   failsafe, and check whether the resources have already been freed,
     234                 :   in each function that requires the resources.
     235                 :   
     236                 :   class derivedClass : public nsISomeInterface,
     237                 :                        public nsNSSShutDownObject
     238                 :   {
     239                 :     virtual void virtualDestroyNSSReference()
     240                 :     {
     241                 :       destructorSafeDestroyNSSReference();
     242                 :     }
     243                 :     
     244                 :     void destructorSafeDestroyNSSReference()
     245                 :     {
     246                 :       if (isAlreadyShutDown())
     247                 :         return;
     248                 :       
     249                 :       // clean up all NSS resources here
     250                 :     }
     251                 : 
     252                 :     virtual ~derivedClass()
     253                 :     {
     254                 :       destructorSafeDestroyNSSReference();
     255                 :       shutdown(calledFromObject);
     256                 :     }
     257                 :     
     258                 :     NS_IMETHODIMP doSomething()
     259                 :     {
     260                 :       if (isAlreadyShutDown())
     261                 :         return NS_ERROR_NOT_AVAILABLE;
     262                 :       
     263                 :       // use the NSS resources and do something
     264                 :     }
     265                 :   };
     266                 : */
     267                 : 
     268                 : class nsNSSShutDownObject
     269                 : {
     270                 : public:
     271                 : 
     272                 :   enum CalledFromType {calledFromList, calledFromObject};
     273                 : 
     274            3654 :   nsNSSShutDownObject()
     275            3654 :   {
     276            3654 :     mAlreadyShutDown = false;
     277            3654 :     nsNSSShutDownList::remember(this);
     278            3654 :   }
     279                 :   
     280            3654 :   virtual ~nsNSSShutDownObject()
     281            3654 :   {
     282                 :     // the derived class must call 
     283                 :     //   shutdown(calledFromObject);
     284                 :     // in its destructor
     285            7308 :   }
     286                 :   
     287            3654 :   void shutdown(CalledFromType calledFrom)
     288                 :   {
     289            3654 :     if (!mAlreadyShutDown) {
     290            3654 :       if (calledFromObject == calledFrom) {
     291            1835 :         nsNSSShutDownList::forget(this);
     292                 :       }
     293            3654 :       if (calledFromList == calledFrom) {
     294            1819 :         virtualDestroyNSSReference();
     295                 :       }
     296            3654 :       mAlreadyShutDown = true;
     297                 :     }
     298            3654 :   }
     299                 :   
     300           10914 :   bool isAlreadyShutDown() { return mAlreadyShutDown; }
     301                 : 
     302                 : protected:
     303                 :   virtual void virtualDestroyNSSReference() = 0;
     304                 : private:
     305                 :   volatile bool mAlreadyShutDown;
     306                 : };
     307                 : 
     308                 : class nsOnPK11LogoutCancelObject
     309                 : {
     310                 : public:
     311               4 :   nsOnPK11LogoutCancelObject()
     312               4 :   :mIsLoggedOut(false)
     313                 :   {
     314               4 :     nsNSSShutDownList::remember(this);
     315               4 :   }
     316                 :   
     317               4 :   virtual ~nsOnPK11LogoutCancelObject()
     318               4 :   {
     319               4 :     nsNSSShutDownList::forget(this);
     320               8 :   }
     321                 :   
     322               0 :   void logout()
     323                 :   {
     324                 :     // We do not care for a race condition.
     325                 :     // Once the bool arrived at false,
     326                 :     // later calls to isPK11LoggedOut() will see it.
     327                 :     // This is a one-time change from 0 to 1.
     328                 :     
     329               0 :     mIsLoggedOut = true;
     330               0 :   }
     331                 :   
     332             326 :   bool isPK11LoggedOut()
     333                 :   {
     334             326 :     return mIsLoggedOut;
     335                 :   }
     336                 : 
     337                 : private:
     338                 :   volatile bool mIsLoggedOut;
     339                 : };
     340                 : 
     341                 : #endif

Generated by: LCOV version 1.7