nsNSSModule.cpp (3769B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "nsNSSModule.h" 8 9 #include "ContentSignatureVerifier.h" 10 #include "OSKeyStore.h" 11 #include "OSReauthenticator.h" 12 #include "PKCS11ModuleDB.h" 13 #include "SecretDecoderRing.h" 14 #include "mozilla/ModuleUtils.h" 15 #include "mozilla/SyncRunnable.h" 16 #include "nsCertTree.h" 17 #include "nsNSSCertificateDB.h" 18 #include "nsPK11TokenDB.h" 19 #include "nsRandomGenerator.h" 20 #include "nsXULAppAPI.h" 21 22 namespace mozilla { 23 namespace psm { 24 25 // Many of the implementations in this module call NSS functions and as a result 26 // require that PSM has successfully initialized NSS before being used. 27 // Additionally, some of the implementations have various restrictions on which 28 // process and threads they can be used on (e.g. some can only be used in the 29 // parent process and some must be initialized only on the main thread). 30 // The following initialization framework allows these requirements to be 31 // succinctly expressed and implemented. 32 33 template <class InstanceClass, nsresult (InstanceClass::*InitMethod)()> 34 MOZ_ALWAYS_INLINE static nsresult Instantiate(REFNSIID aIID, void** aResult) { 35 InstanceClass* inst = new InstanceClass(); 36 NS_ADDREF(inst); 37 nsresult rv = InitMethod != nullptr ? (inst->*InitMethod)() : NS_OK; 38 if (NS_SUCCEEDED(rv)) { 39 rv = inst->QueryInterface(aIID, aResult); 40 } 41 NS_RELEASE(inst); 42 return rv; 43 } 44 45 enum class ThreadRestriction { 46 // must be initialized on the main thread (but can be used on any thread) 47 MainThreadOnly, 48 // can be initialized and used on any thread 49 AnyThread, 50 }; 51 52 enum class ProcessRestriction { 53 ParentProcessOnly, 54 AnyProcess, 55 }; 56 57 template <class InstanceClass, 58 nsresult (InstanceClass::*InitMethod)() = nullptr, 59 ProcessRestriction processRestriction = 60 ProcessRestriction::ParentProcessOnly, 61 ThreadRestriction threadRestriction = ThreadRestriction::AnyThread> 62 static nsresult Constructor(REFNSIID aIID, void** aResult) { 63 *aResult = nullptr; 64 65 if (processRestriction == ProcessRestriction::ParentProcessOnly && 66 !XRE_IsParentProcess()) { 67 return NS_ERROR_NOT_AVAILABLE; 68 } 69 70 if (!EnsureNSSInitializedChromeOrContent()) { 71 return NS_ERROR_FAILURE; 72 } 73 74 if (threadRestriction == ThreadRestriction::MainThreadOnly && 75 !NS_IsMainThread()) { 76 return NS_ERROR_NOT_SAME_THREAD; 77 } 78 79 return Instantiate<InstanceClass, InitMethod>(aIID, aResult); 80 } 81 82 #define IMPL(type, ...) \ 83 template <> \ 84 nsresult NSSConstructor<type>(const nsIID& aIID, void** aResult) { \ 85 return Constructor<type, __VA_ARGS__>(aIID, aResult); \ 86 } 87 88 // Components that require main thread initialization could cause a deadlock 89 // in necko code (bug 1418752). To prevent it we initialize all such components 90 // on main thread in advance in net_EnsurePSMInit(). Update that function when 91 // new component with ThreadRestriction::MainThreadOnly is added. 92 IMPL(SecretDecoderRing, nullptr) 93 IMPL(nsPK11TokenDB, nullptr) 94 IMPL(PKCS11ModuleDB, nullptr) 95 IMPL(nsNSSCertificateDB, nullptr) 96 IMPL(nsCertTree, nullptr) 97 IMPL(ContentSignatureVerifier, nullptr) 98 IMPL(nsRandomGenerator, nullptr, ProcessRestriction::AnyProcess) 99 IMPL(OSKeyStore, nullptr, ProcessRestriction::ParentProcessOnly, 100 ThreadRestriction::MainThreadOnly) 101 IMPL(OSReauthenticator, nullptr, ProcessRestriction::ParentProcessOnly, 102 ThreadRestriction::MainThreadOnly) 103 #undef IMPL 104 105 } // namespace psm 106 } // namespace mozilla