[go: nahoru, domu]

Extract ScopedTestNSSDB from nss_util.

Before ScopedTestNSSDB affected several slot getters from nss_util.h .
This change reduces ScopedTestNSSDB to solely setup a temporary test DB and not influencing the global state in nss_util anymore.

As a replacement for some of its old behavior, a new ScopedTestSystemNSSKeySlot is added, which allows to override the slot returned by GetSystemNSSKeySlot().

With this change it's now possible to write tests that need both a user and system NSS DB by using ScopedTestSystemNSSKeySlot.

As a side-effect, GetPersistentNSSKeySlot() is now compiled on !OS_CHROMEOS only.

BUG=210525
(For include changes:)

R=rsleevi@chromium.org
TBR=nkostylev@chromium.org, stevenjb@chromium.org

Review URL: https://codereview.chromium.org/401623006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285881 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc
index 9985b8d7..248defa 100644
--- a/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/auth/parallel_authenticator_unittest.cc
@@ -37,8 +37,8 @@
 #include "chromeos/login/auth/user_context.h"
 #include "components/user_manager/user.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "google_apis/gaia/mock_url_fetcher_factory.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_request_status.h"
diff --git a/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc b/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc
index f03876e..0080355 100644
--- a/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
 
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_data_directory.h"
 #include "net/cert/cert_verify_proc.h"
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
index bcb50576..37a3243 100644
--- a/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
+++ b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
@@ -13,8 +13,8 @@
 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/net_log.h"
 #include "net/base/test_completion_callback.h"
 #include "net/base/test_data_directory.h"
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index d60a269..2b995bf 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1835,8 +1835,8 @@
       'browser/certificate_manager_model.cc',
       'browser/certificate_manager_model.h',
       'browser/net/nss_context.cc',
-      'browser/net/nss_context_chromeos.cc',
       'browser/net/nss_context.h',
+      'browser/net/nss_context_chromeos.cc',
       'browser/net/nss_context_linux.cc',
       'third_party/mozilla_security_manager/nsNSSCertHelper.cpp',
       'third_party/mozilla_security_manager/nsNSSCertHelper.h',
@@ -3234,6 +3234,13 @@
         }],
         ['use_nss==1', {
           'sources': [ '<@(chrome_browser_nss_sources)' ],
+          'conditions': [
+            ['chromeos==1', {
+               'sources!': [ 'browser/net/nss_context_linux.cc' ],
+              }, { # chromeos==0
+               'sources!': [ 'browser/net/nss_context_chromeos.cc' ],
+              }],
+          ],
         }],
         ['notifications==1', {
           'sources': [ '<@(chrome_browser_notifications_sources)' ],
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 7d7736b..c950057 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -796,6 +796,7 @@
         '../components/components.gyp:translate_core_common',
         '../components/components_resources.gyp:components_resources',
         '../components/components_strings.gyp:components_strings',
+        '../crypto/crypto.gyp:crypto_test_support',
         '../device/bluetooth/bluetooth.gyp:device_bluetooth_mocks',
         '../device/serial/serial.gyp:device_serial_test_util',
         '../extensions/common/api/api.gyp:extensions_api',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 4a23bc5..f6e9c6a0 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -490,6 +490,7 @@
         '../components/components_resources.gyp:components_resources',
         '../content/content_shell_and_tests.gyp:test_support_content',
         '../content/content.gyp:content_app_both',
+        '../crypto/crypto.gyp:crypto_test_support',
         '../net/net.gyp:net',
         '../net/net.gyp:net_test_support',
         '../sync/sync.gyp:test_support_sync_api',
diff --git a/chrome/common/net/x509_certificate_model_unittest.cc b/chrome/common/net/x509_certificate_model_unittest.cc
index 8d010d7..37f3fe4 100644
--- a/chrome/common/net/x509_certificate_model_unittest.cc
+++ b/chrome/common/net/x509_certificate_model_unittest.cc
@@ -11,7 +11,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(USE_NSS)
-#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_db.h"
 #include "net/cert/nss_cert_database.h"
 #endif
 
@@ -224,12 +224,11 @@
   EXPECT_EQ(net::CA_CERT,
             x509_certificate_model::GetType(cert->os_cert_handle()));
 
-  // Additional parantheses required to disambiguate from function declaration.
-  net::NSSCertDatabase db(
-      (crypto::ScopedPK11Slot(
-          crypto::GetPersistentNSSKeySlot())) /* public slot */,
-      crypto::ScopedPK11Slot(
-          crypto::GetPersistentNSSKeySlot()) /* private lot */);
+  crypto::ScopedTestNSSDB test_nssdb;
+  net::NSSCertDatabase db(crypto::ScopedPK11Slot(PK11_ReferenceSlot(
+                              test_nssdb.slot())) /* public slot */,
+                          crypto::ScopedPK11Slot(PK11_ReferenceSlot(
+                              test_nssdb.slot())) /* private slot */);
 
   // Test that explicitly distrusted CA certs are still returned as CA_CERT
   // type. See http://crbug.com/96654.
@@ -259,12 +258,11 @@
   EXPECT_EQ(net::OTHER_CERT,
             x509_certificate_model::GetType(cert->os_cert_handle()));
 
-  // Additional parantheses required to disambiguate from function declaration.
-  net::NSSCertDatabase db(
-      (crypto::ScopedPK11Slot(
-          crypto::GetPersistentNSSKeySlot())) /* public slot */,
-      crypto::ScopedPK11Slot(
-          crypto::GetPersistentNSSKeySlot()) /* private lot */);
+  crypto::ScopedTestNSSDB test_nssdb;
+  net::NSSCertDatabase db(crypto::ScopedPK11Slot(PK11_ReferenceSlot(
+                              test_nssdb.slot())) /* public slot */,
+                          crypto::ScopedPK11Slot(PK11_ReferenceSlot(
+                              test_nssdb.slot())) /* private slot */);
 
   // Test GetCertType with server certs and explicit trust.
   EXPECT_TRUE(db.SetCertTrust(
diff --git a/chromeos/cert_loader_unittest.cc b/chromeos/cert_loader_unittest.cc
index 216a8db..a7efa21 100644
--- a/chromeos/cert_loader_unittest.cc
+++ b/chromeos/cert_loader_unittest.cc
@@ -9,9 +9,9 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
 #include "crypto/scoped_nss_types.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_data_directory.h"
 #include "net/cert/nss_cert_database_chromeos.h"
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 9b07040..da86460 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -511,6 +511,7 @@
         '../build/linux/system.gyp:ssl',
         '../components/components.gyp:onc_component',
         '../crypto/crypto.gyp:crypto',
+        '../crypto/crypto.gyp:crypto_test_support',
         '../dbus/dbus.gyp:dbus_test_support',
         '../net/net.gyp:net',
         '../net/net.gyp:net_test_support',
diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc
index 4ca251e..86f45ac 100644
--- a/chromeos/network/client_cert_resolver_unittest.cc
+++ b/chromeos/network/client_cert_resolver_unittest.cc
@@ -23,8 +23,8 @@
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/tpm_token_loader.h"
 #include "components/onc/onc_constants.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/crypto_module.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_data_directory.h"
diff --git a/chromeos/network/network_cert_migrator_unittest.cc b/chromeos/network/network_cert_migrator_unittest.cc
index 1482ec3..2f72cfd 100644
--- a/chromeos/network/network_cert_migrator_unittest.cc
+++ b/chromeos/network/network_cert_migrator_unittest.cc
@@ -14,8 +14,8 @@
 #include "chromeos/dbus/shill_service_client.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/tpm_token_loader.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/crypto_module.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_data_directory.h"
diff --git a/chromeos/network/network_connection_handler_unittest.cc b/chromeos/network/network_connection_handler_unittest.cc
index 5dc9de3..5725432 100644
--- a/chromeos/network/network_connection_handler_unittest.cc
+++ b/chromeos/network/network_connection_handler_unittest.cc
@@ -25,8 +25,8 @@
 #include "chromeos/network/onc/onc_utils.h"
 #include "chromeos/tpm_token_loader.h"
 #include "components/onc/onc_constants.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_data_directory.h"
 #include "net/cert/nss_cert_database_chromeos.h"
diff --git a/chromeos/network/onc/onc_certificate_importer_impl_unittest.cc b/chromeos/network/onc/onc_certificate_importer_impl_unittest.cc
index fef0508..bb05d14 100644
--- a/chromeos/network/onc/onc_certificate_importer_impl_unittest.cc
+++ b/chromeos/network/onc/onc_certificate_importer_impl_unittest.cc
@@ -16,8 +16,8 @@
 #include "base/values.h"
 #include "chromeos/network/onc/onc_test_utils.h"
 #include "components/onc/onc_constants.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/crypto_module.h"
 #include "net/cert/cert_type.h"
 #include "net/cert/nss_cert_database_chromeos.h"
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index bd7f06d..6871bda0 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -131,6 +131,7 @@
       "hmac_nss.cc",
       "nss_util.cc",
       "nss_util.h",
+      "nss_util_internal.h",
       "rsa_private_key_nss.cc",
       "secure_hash_default.cc",
       "signature_creator_nss.cc",
@@ -229,6 +230,7 @@
   deps = [
     ":crypto",
     ":platform",
+    ":test_support",
     "//base",
     "//base/test:run_all_unittests",
     "//base/test:test_support",
@@ -237,6 +239,38 @@
   ]
 }
 
+source_set("test_support") {
+  sources = [
+    "scoped_test_nss_db.cc",
+    "scoped_test_nss_db.h",
+    "scoped_test_nss_chromeos_user.cc",
+    "scoped_test_nss_chromeos_user.h",
+    "scoped_test_system_nss_key_slot.cc",
+    "scoped_test_system_nss_key_slot.h",
+  ]
+  deps = [
+    ":crypto",
+    ":platform",
+    "//base",
+  ]
+
+  if (!use_nss_certs) {
+    sources -= [
+      "scoped_test_nss_db.cc",
+      "scoped_test_nss_db.h",
+    ]
+  }
+
+  if (!is_chromeos) {
+    sources -= [
+      "scoped_test_nss_chromeos_user.cc",
+      "scoped_test_nss_chromeos_user.h",
+      "scoped_test_system_nss_key_slot.cc",
+      "scoped_test_system_nss_key_slot.h",
+    ]
+  }
+}
+
 # This is a meta-target that forwards to NSS's SSL library or OpenSSL,
 # according to the state of the crypto flags. A target just wanting to depend
 # on the current SSL library should just depend on this.
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index 42f3cad..3cdc151f 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -111,6 +111,7 @@
               'hmac_nss.cc',
               'nss_util.cc',
               'nss_util.h',
+              'nss_util_internal.h',
               'rsa_private_key_nss.cc',
               'secure_hash_default.cc',
               'signature_creator_nss.cc',
@@ -174,6 +175,7 @@
       ],
       'dependencies': [
         'crypto',
+        'crypto_test_support',
         '../base/base.gyp:base',
         '../base/base.gyp:run_all_unittests',
         '../base/base.gyp:test_support_base',
@@ -254,5 +256,47 @@
         },
       ],
     }],
+    ['use_nss==1', {
+      'targets': [
+        {
+          'target_name': 'crypto_test_support',
+          'type': 'static_library',
+          'dependencies': [
+            '../base/base.gyp:base',
+            'crypto',
+          ],
+          'sources': [
+            'scoped_test_nss_db.cc',
+            'scoped_test_nss_db.h',
+            'scoped_test_nss_chromeos_user.cc',
+            'scoped_test_nss_chromeos_user.h',
+            'scoped_test_system_nss_key_slot.cc',
+            'scoped_test_system_nss_key_slot.h',
+          ],
+          'conditions': [
+            ['use_nss==0', {
+              'sources!': [
+                'scoped_test_nss_db.cc',
+                'scoped_test_nss_db.h',
+              ],
+            }],
+            [ 'chromeos==0', {
+              'sources!': [
+                'scoped_test_nss_chromeos_user.cc',
+                'scoped_test_nss_chromeos_user.h',
+                'scoped_test_system_nss_key_slot.cc',
+                'scoped_test_system_nss_key_slot.h',
+              ],
+            }],
+          ],
+        }
+      ]}, {  # use_nss==0
+      'targets': [
+        {
+          'target_name': 'crypto_test_support',
+          'type': 'none',
+          'sources': [],
+        }
+    ]}],
   ],
 }
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
index 6ab07bc8..64489dc 100644
--- a/crypto/nss_util.cc
+++ b/crypto/nss_util.cc
@@ -198,12 +198,6 @@
 base::LazyInstance<NSPRInitSingleton>::Leaky
     g_nspr_singleton = LAZY_INSTANCE_INITIALIZER;
 
-// This is a LazyInstance so that it will be deleted automatically when the
-// unittest exits.  NSSInitSingleton is a LeakySingleton, so it would not be
-// deleted if it were a regular member.
-base::LazyInstance<base::ScopedTempDir> g_test_nss_db_dir =
-    LAZY_INSTANCE_INITIALIZER;
-
 // Force a crash with error info on NSS_NoDB_Init failure.
 void CrashOnNSSInitFailure() {
   int nss_error = PR_GetError();
@@ -287,8 +281,8 @@
     PK11SlotInfo* tpm_slot;
   };
 
-  PK11SlotInfo* OpenPersistentNSSDBForPath(const std::string& db_name,
-                                           const base::FilePath& path) {
+  ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name,
+                                            const base::FilePath& path) {
     DCHECK(thread_checker_.CalledOnValidThread());
     // NSS is allowed to do IO on the current thread since dispatching
     // to a dedicated thread would still have the affect of blocking
@@ -298,9 +292,9 @@
     base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb");
     if (!base::CreateDirectory(nssdb_path)) {
       LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
-      return NULL;
+      return ScopedPK11Slot();
     }
-    return OpenUserDB(nssdb_path, db_name);
+    return OpenSoftwareNSSDB(nssdb_path, db_name);
   }
 
   void EnableTPMTokenForNSS() {
@@ -393,10 +387,10 @@
 
     chaps_module_ = tpm_args->chaps_module;
     tpm_slot_ = tpm_args->tpm_slot;
-    if (!chaps_module_ && test_slot_) {
+    if (!chaps_module_ && test_system_slot_) {
       // chromeos_unittests try to test the TPM initialization process. If we
       // have a test DB open, pretend that it is the TPM slot.
-      tpm_slot_ = PK11_ReferenceSlot(test_slot_);
+      tpm_slot_ = PK11_ReferenceSlot(test_system_slot_.get());
     }
     initializing_tpm_token_ = false;
 
@@ -463,12 +457,6 @@
       return false;
     }
 
-    // If test slot is set, slot getter methods will short circuit
-    // checking |chromeos_user_map_|, so there is nothing left to be
-    // initialized.
-    if (test_slot_)
-      return false;
-
     DVLOG(2) << "Opening NSS DB " << path.value();
     std::string db_name = base::StringPrintf(
         "%s %s", kUserNSSDatabaseName, username_hash.c_str());
@@ -551,11 +539,6 @@
       return ScopedPK11Slot();
     }
 
-    if (test_slot_) {
-      DVLOG(2) << "returning test_slot_ for " << username_hash;
-      return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_));
-    }
-
     if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) {
       LOG(ERROR) << username_hash << " not initialized.";
       return ScopedPK11Slot();
@@ -579,56 +562,26 @@
 
     DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
 
-    if (test_slot_) {
-      DVLOG(2) << "returning test_slot_ for " << username_hash;
-      return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_));
-    }
-
     return chromeos_user_map_[username_hash]->GetPrivateSlot(callback);
   }
 
-  void CloseTestChromeOSUser(const std::string& username_hash) {
+  void CloseChromeOSUserForTesting(const std::string& username_hash) {
     DCHECK(thread_checker_.CalledOnValidThread());
     ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash);
     DCHECK(i != chromeos_user_map_.end());
     delete i->second;
     chromeos_user_map_.erase(i);
   }
+
+  void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
+    // Ensure that a previous value of test_system_slot_ is not overwritten.
+    // Unsetting, i.e. setting a NULL, however is allowed.
+    DCHECK(!slot || !test_system_slot_);
+    test_system_slot_ = slot.Pass();
+  }
 #endif  // defined(OS_CHROMEOS)
 
-
-  bool OpenTestNSSDB() {
-    DCHECK(thread_checker_.CalledOnValidThread());
-    // NSS is allowed to do IO on the current thread since dispatching
-    // to a dedicated thread would still have the affect of blocking
-    // the current thread, due to NSS's internal locking requirements
-    base::ThreadRestrictions::ScopedAllowIO allow_io;
-
-    if (test_slot_)
-      return true;
-    if (!g_test_nss_db_dir.Get().CreateUniqueTempDir())
-      return false;
-    test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName);
-    return !!test_slot_;
-  }
-
-  void CloseTestNSSDB() {
-    DCHECK(thread_checker_.CalledOnValidThread());
-    // NSS is allowed to do IO on the current thread since dispatching
-    // to a dedicated thread would still have the affect of blocking
-    // the current thread, due to NSS's internal locking requirements
-    base::ThreadRestrictions::ScopedAllowIO allow_io;
-
-    if (!test_slot_)
-      return;
-    SECStatus status = SECMOD_CloseUserDB(test_slot_);
-    if (status != SECSuccess)
-      PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
-    PK11_FreeSlot(test_slot_);
-    test_slot_ = NULL;
-    ignore_result(g_test_nss_db_dir.Get().Delete());
-  }
-
+#if !defined(OS_CHROMEOS)
   PK11SlotInfo* GetPersistentNSSKeySlot() {
     // TODO(mattm): Change to DCHECK when callers have been fixed.
     if (!thread_checker_.CalledOnValidThread()) {
@@ -636,18 +589,14 @@
                << base::debug::StackTrace().ToString();
     }
 
-    if (test_slot_)
-      return PK11_ReferenceSlot(test_slot_);
     return PK11_GetInternalKeySlot();
   }
+#endif
 
 #if defined(OS_CHROMEOS)
   PK11SlotInfo* GetSystemNSSKeySlot() {
     DCHECK(thread_checker_.CalledOnValidThread());
 
-    if (test_slot_)
-      return PK11_ReferenceSlot(test_slot_);
-
     // TODO(mattm): chromeos::TPMTokenloader always calls
     // InitializeTPMTokenAndSystemSlot with slot 0.  If the system slot is
     // disabled, tpm_slot_ will be the first user's slot instead. Can that be
@@ -679,7 +628,6 @@
       : tpm_token_enabled_for_nss_(false),
         initializing_tpm_token_(false),
         chaps_module_(NULL),
-        test_slot_(NULL),
         tpm_slot_(NULL),
         root_(NULL) {
     base::TimeTicks start_time = base::TimeTicks::Now();
@@ -801,7 +749,6 @@
       PK11_FreeSlot(tpm_slot_);
       tpm_slot_ = NULL;
     }
-    CloseTestNSSDB();
     if (root_) {
       SECMOD_UnloadUserModule(root_);
       SECMOD_DestroyModule(root_);
@@ -863,23 +810,6 @@
   }
 #endif
 
-  static PK11SlotInfo* OpenUserDB(const base::FilePath& path,
-                                  const std::string& description) {
-    const std::string modspec =
-        base::StringPrintf("configDir='sql:%s' tokenDescription='%s'",
-                           path.value().c_str(),
-                           description.c_str());
-    PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str());
-    if (db_slot) {
-      if (PK11_NeedUserInit(db_slot))
-        PK11_InitPin(db_slot, NULL, NULL);
-    } else {
-      LOG(ERROR) << "Error opening persistent database (" << modspec
-                 << "): " << GetNSSErrorMessage();
-    }
-    return db_slot;
-  }
-
   static void DisableAESNIIfNeeded() {
     if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) {
       // Some versions of NSS have a bug that causes AVX instructions to be
@@ -903,12 +833,12 @@
   typedef std::vector<base::Closure> TPMReadyCallbackList;
   TPMReadyCallbackList tpm_ready_callback_list_;
   SECMODModule* chaps_module_;
-  PK11SlotInfo* test_slot_;
   PK11SlotInfo* tpm_slot_;
   SECMODModule* root_;
 #if defined(OS_CHROMEOS)
   typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap;
   ChromeOSUserMap chromeos_user_map_;
+  ScopedPK11Slot test_system_slot_;
 #endif
 #if defined(USE_NSS)
   // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011
@@ -926,9 +856,24 @@
     g_nss_singleton = LAZY_INSTANCE_INITIALIZER;
 }  // namespace
 
-const char kTestTPMTokenName[] = "Test DB";
-
 #if defined(USE_NSS)
+ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path,
+                                 const std::string& description) {
+  const std::string modspec =
+      base::StringPrintf("configDir='sql:%s' tokenDescription='%s'",
+                         path.value().c_str(),
+                         description.c_str());
+  PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str());
+  if (db_slot) {
+    if (PK11_NeedUserInit(db_slot))
+      PK11_InitPin(db_slot, NULL, NULL);
+  } else {
+    LOG(ERROR) << "Error opening persistent database (" << modspec
+               << "): " << GetNSSErrorMessage();
+  }
+  return ScopedPK11Slot(db_slot);
+}
+
 void EarlySetupForNSSInit() {
   base::FilePath database_dir = GetInitialConfigDirectory();
   if (!database_dir.empty())
@@ -1027,19 +972,6 @@
 }
 
 #if defined(USE_NSS)
-ScopedTestNSSDB::ScopedTestNSSDB()
-  : is_open_(g_nss_singleton.Get().OpenTestNSSDB()) {
-}
-
-ScopedTestNSSDB::~ScopedTestNSSDB() {
-  // Don't close when NSS is < 3.15.1, because it would require an additional
-  // sleep for 1 second after closing the database, due to
-  // http://bugzil.la/875601.
-  if (NSS_VersionCheck("3.15.1")) {
-    g_nss_singleton.Get().CloseTestNSSDB();
-  }
-}
-
 base::Lock* GetNSSWriteLock() {
   return g_nss_singleton.Get().write_lock();
 }
@@ -1065,7 +997,6 @@
 AutoSECMODListReadLock::~AutoSECMODListReadLock() {
   SECMOD_ReleaseReadLock(lock_);
 }
-
 #endif  // defined(USE_NSS)
 
 #if defined(OS_CHROMEOS)
@@ -1073,6 +1004,10 @@
   return g_nss_singleton.Get().GetSystemNSSKeySlot();
 }
 
+void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
+  g_nss_singleton.Get().SetSystemKeySlotForTesting(ScopedPK11Slot());
+}
+
 void EnableTPMTokenForNSS() {
   g_nss_singleton.Get().EnableTPMTokenForNSS();
 }
@@ -1092,30 +1027,6 @@
                                                         callback);
 }
 
-ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser(
-    const std::string& username_hash)
-    : username_hash_(username_hash), constructed_successfully_(false) {
-  if (!temp_dir_.CreateUniqueTempDir())
-    return;
-  constructed_successfully_ =
-      InitializeNSSForChromeOSUser(username_hash,
-                                   username_hash,
-                                   temp_dir_.path());
-}
-
-ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() {
-  if (constructed_successfully_)
-    g_nss_singleton.Get().CloseTestChromeOSUser(username_hash_);
-}
-
-void ScopedTestNSSChromeOSUser::FinishInit() {
-  DCHECK(constructed_successfully_);
-  if (!ShouldInitializeTPMForChromeOSUser(username_hash_))
-    return;
-  WillInitializeTPMForChromeOSUser(username_hash_);
-  InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
-}
-
 bool InitializeNSSForChromeOSUser(
     const std::string& email,
     const std::string& username_hash,
@@ -1138,20 +1049,27 @@
     CK_SLOT_ID slot_id) {
   g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id);
 }
+
 void InitializePrivateSoftwareSlotForChromeOSUser(
     const std::string& username_hash) {
   g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser(
       username_hash);
 }
+
 ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) {
   return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash);
 }
+
 ScopedPK11Slot GetPrivateSlotForChromeOSUser(
     const std::string& username_hash,
     const base::Callback<void(ScopedPK11Slot)>& callback) {
   return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(username_hash,
                                                              callback);
 }
+
+void CloseChromeOSUserForTesting(const std::string& username_hash) {
+  g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash);
+}
 #endif  // defined(OS_CHROMEOS)
 
 base::Time PRTimeToBaseTime(PRTime prtime) {
@@ -1163,8 +1081,10 @@
   return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue();
 }
 
+#if !defined(OS_CHROMEOS)
 PK11SlotInfo* GetPersistentNSSKeySlot() {
   return g_nss_singleton.Get().GetPersistentNSSKeySlot();
 }
+#endif
 
 }  // namespace crypto
diff --git a/crypto/nss_util.h b/crypto/nss_util.h
index 0efdbc2..56fdfa6 100644
--- a/crypto/nss_util.h
+++ b/crypto/nss_util.h
@@ -9,7 +9,6 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/compiler_specific.h"
-#include "base/files/scoped_temp_dir.h"
 #include "crypto/crypto_export.h"
 
 namespace base {
@@ -23,9 +22,6 @@
 // initialization functions.
 namespace crypto {
 
-// The TPMToken name used for the NSS slot opened by ScopedTestNSSDB.
-CRYPTO_EXPORT extern const char kTestTPMTokenName[];
-
 #if defined(USE_NSS)
 // EarlySetupForNSSInit performs lightweight setup which must occur before the
 // process goes multithreaded. This does not initialise NSS. For test, see
@@ -121,26 +117,6 @@
 CRYPTO_EXPORT void InitializeTPMTokenAndSystemSlot(
     int system_slot_id,
     const base::Callback<void(bool)>& callback);
-
-// Exposed for unittests only.
-class CRYPTO_EXPORT_PRIVATE ScopedTestNSSChromeOSUser {
- public:
-  explicit ScopedTestNSSChromeOSUser(const std::string& username_hash);
-  ~ScopedTestNSSChromeOSUser();
-
-  std::string username_hash() const { return username_hash_; }
-  bool constructed_successfully() const { return constructed_successfully_; }
-
-  // Completes initialization of user. Causes any waiting private slot callbacks
-  // to run.
-  void FinishInit();
-
- private:
-  const std::string username_hash_;
-  base::ScopedTempDir temp_dir_;
-  bool constructed_successfully_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser);
-};
 #endif
 
 // Convert a NSS PRTime value into a base::Time object.
@@ -152,23 +128,6 @@
 CRYPTO_EXPORT int64 BaseTimeToPRTime(base::Time time);
 
 #if defined(USE_NSS)
-// Exposed for unittests only.
-// TODO(mattm): When NSS 3.14 is the minimum version required,
-// switch back to using a separate user DB for each test.
-// Because of https://bugzilla.mozilla.org/show_bug.cgi?id=588269 , the
-// opened user DB is not automatically closed.
-class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB {
- public:
-  ScopedTestNSSDB();
-  ~ScopedTestNSSDB();
-
-  bool is_open() { return is_open_; }
-
- private:
-  bool is_open_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB);
-};
-
 // NSS has a bug which can cause a deadlock or stall in some cases when writing
 // to the certDB and keyDB. It also has a bug which causes concurrent key pair
 // generations to scribble over each other. To work around this, we synchronize
@@ -189,7 +148,6 @@
   base::Lock *lock_;
   DISALLOW_COPY_AND_ASSIGN(AutoNSSWriteLock);
 };
-
 #endif  // defined(USE_NSS)
 
 }  // namespace crypto
diff --git a/crypto/nss_util_internal.h b/crypto/nss_util_internal.h
index e9d4870..c40295f 100644
--- a/crypto/nss_util_internal.h
+++ b/crypto/nss_util_internal.h
@@ -21,11 +21,18 @@
 
 namespace crypto {
 
+// Opens an NSS software database in folder |path|, with the (potentially)
+// user-visible description |description|. Returns the slot for the opened
+// database, or NULL if the database could not be opened.
+CRYPTO_EXPORT_PRIVATE ScopedPK11Slot
+    OpenSoftwareNSSDB(const base::FilePath& path,
+                      const std::string& description);
+
+#if !defined(OS_CHROMEOS)
 // Returns a reference to the default NSS key slot for storing persistent data.
 // Caller must release returned reference with PK11_FreeSlot.
-// TODO(mattm): this should be if !defined(OS_CHROMEOS), but some tests need to
-// be fixed first.
 CRYPTO_EXPORT PK11SlotInfo* GetPersistentNSSKeySlot() WARN_UNUSED_RESULT;
+#endif
 
 // A helper class that acquires the SECMOD list read lock while the
 // AutoSECMODListReadLock is in scope.
@@ -40,10 +47,19 @@
 };
 
 #if defined(OS_CHROMEOS)
-// Returns a reference to the system-wide TPM slot.  Caller must release
-// returned reference with PK11_FreeSlot.
+// Returns a reference to the system-wide TPM slot. Caller must release returned
+// reference with PK11_FreeSlot.
 CRYPTO_EXPORT PK11SlotInfo* GetSystemNSSKeySlot() WARN_UNUSED_RESULT;
 
+// Sets the test system slot. If this was called before
+// InitializeTPMTokenAndSystemSlot and no system token is provided by the Chaps
+// module, then this test slot will be used and the initialization continues as
+// if Chaps had provided this test slot. In particular, |slot| will be exposed
+// by |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true.
+// This must must not be called consecutively with a |slot| != NULL. If |slot|
+// is NULL, the test system slot is unset.
+CRYPTO_EXPORT_PRIVATE void SetSystemKeySlotForTesting(ScopedPK11Slot slot);
+
 // Prepare per-user NSS slot mapping. It is safe to call this function multiple
 // times. Returns true if the user was added, or false if it already existed.
 CRYPTO_EXPORT bool InitializeNSSForChromeOSUser(
@@ -85,6 +101,11 @@
 CRYPTO_EXPORT ScopedPK11Slot GetPrivateSlotForChromeOSUser(
     const std::string& username_hash,
     const base::Callback<void(ScopedPK11Slot)>& callback) WARN_UNUSED_RESULT;
+
+// Closes the NSS DB for |username_hash| that was previously opened by the
+// *Initialize*ForChromeOSUser functions.
+CRYPTO_EXPORT_PRIVATE void CloseChromeOSUserForTesting(
+    const std::string& username_hash);
 #endif  // defined(OS_CHROMEOS)
 
 }  // namespace crypto
diff --git a/crypto/rsa_private_key_nss_unittest.cc b/crypto/rsa_private_key_nss_unittest.cc
index f376f15..4adb9db 100644
--- a/crypto/rsa_private_key_nss_unittest.cc
+++ b/crypto/rsa_private_key_nss_unittest.cc
@@ -8,7 +8,7 @@
 #include <pk11pub.h>
 
 #include "base/memory/scoped_ptr.h"
-#include "crypto/nss_util.h"
+#include "crypto/scoped_test_nss_db.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace crypto {
diff --git a/crypto/scoped_test_nss_chromeos_user.cc b/crypto/scoped_test_nss_chromeos_user.cc
new file mode 100644
index 0000000..20eadf49
--- /dev/null
+++ b/crypto/scoped_test_nss_chromeos_user.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/scoped_test_nss_chromeos_user.h"
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+
+namespace crypto {
+
+ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser(
+    const std::string& username_hash)
+    : username_hash_(username_hash), constructed_successfully_(false) {
+  if (!temp_dir_.CreateUniqueTempDir())
+    return;
+  // This opens a software DB in the given folder. In production code that is in
+  // the home folder, but for testing the temp folder is used.
+  constructed_successfully_ = InitializeNSSForChromeOSUser(
+      username_hash, username_hash, temp_dir_.path());
+}
+
+ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() {
+  if (constructed_successfully_)
+    CloseChromeOSUserForTesting(username_hash_);
+}
+
+void ScopedTestNSSChromeOSUser::FinishInit() {
+  DCHECK(constructed_successfully_);
+  if (!ShouldInitializeTPMForChromeOSUser(username_hash_))
+    return;
+  WillInitializeTPMForChromeOSUser(username_hash_);
+  InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
+}
+
+}  // namespace crypto
diff --git a/crypto/scoped_test_nss_chromeos_user.h b/crypto/scoped_test_nss_chromeos_user.h
new file mode 100644
index 0000000..1638517
--- /dev/null
+++ b/crypto/scoped_test_nss_chromeos_user.h
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
+#define CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
+
+#include <string>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// Opens a persistent NSS software database in a temporary directory for the
+// user with |username_hash|. This database will be used for both the user's
+// public and private slot.
+class CRYPTO_EXPORT_PRIVATE ScopedTestNSSChromeOSUser {
+ public:
+  // Opens the software database and sets the public slot for the user. The
+  // private slot will not be initialized until FinishInit() is called.
+  explicit ScopedTestNSSChromeOSUser(const std::string& username_hash);
+  ~ScopedTestNSSChromeOSUser();
+
+  std::string username_hash() const { return username_hash_; }
+  bool constructed_successfully() const { return constructed_successfully_; }
+
+  // Completes initialization of user. Causes any waiting private slot callbacks
+  // to run, see GetPrivateSlotForChromeOSUser().
+  void FinishInit();
+
+ private:
+  const std::string username_hash_;
+  base::ScopedTempDir temp_dir_;
+  bool constructed_successfully_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
diff --git a/crypto/scoped_test_nss_db.cc b/crypto/scoped_test_nss_db.cc
new file mode 100644
index 0000000..a3ff68b8
--- /dev/null
+++ b/crypto/scoped_test_nss_db.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/scoped_test_nss_db.h"
+
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+
+namespace crypto {
+
+ScopedTestNSSDB::ScopedTestNSSDB() {
+  EnsureNSSInit();
+  // NSS is allowed to do IO on the current thread since dispatching
+  // to a dedicated thread would still have the affect of blocking
+  // the current thread, due to NSS's internal locking requirements
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+  if (!temp_dir_.CreateUniqueTempDir())
+    return;
+
+  const char kTestDescription[] = "Test DB";
+  slot_ = OpenSoftwareNSSDB(temp_dir_.path(), kTestDescription);
+}
+
+ScopedTestNSSDB::~ScopedTestNSSDB() {
+  // Don't close when NSS is < 3.15.1, because it would require an additional
+  // sleep for 1 second after closing the database, due to
+  // http://bugzil.la/875601.
+  if (!NSS_VersionCheck("3.15.1") || !slot_)
+    return;
+
+  // NSS is allowed to do IO on the current thread since dispatching
+  // to a dedicated thread would still have the affect of blocking
+  // the current thread, due to NSS's internal locking requirements
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+  SECStatus status = SECMOD_CloseUserDB(slot_.get());
+  if (status != SECSuccess)
+    PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
+
+  if (!temp_dir_.Delete())
+    LOG(ERROR) << "Could not delete temporary directory.";
+}
+
+}  // namespace crypto
diff --git a/crypto/scoped_test_nss_db.h b/crypto/scoped_test_nss_db.h
new file mode 100644
index 0000000..cc6996d
--- /dev/null
+++ b/crypto/scoped_test_nss_db.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_TEST_NSS_DB_H_
+#define CRYPTO_SCOPED_TEST_NSS_DB_H_
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "crypto/crypto_export.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace crypto {
+
+// Opens a persistent NSS database in a temporary directory.
+// Prior NSS version 3.15.1, because of http://bugzil.la/875601 , the opened DB
+// will not be closed automatically.
+class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB {
+ public:
+  ScopedTestNSSDB();
+  ~ScopedTestNSSDB();
+
+  bool is_open() { return slot_; }
+  PK11SlotInfo* slot() { return slot_.get(); }
+
+ private:
+  base::ScopedTempDir temp_dir_;
+  ScopedPK11Slot slot_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_NSS_DB_H_
diff --git a/crypto/scoped_test_system_nss_key_slot.cc b/crypto/scoped_test_system_nss_key_slot.cc
new file mode 100644
index 0000000..ee5e1df
--- /dev/null
+++ b/crypto/scoped_test_system_nss_key_slot.cc
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/scoped_test_system_nss_key_slot.h"
+
+#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_db.h"
+
+namespace crypto {
+
+ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot()
+    : test_db_(new ScopedTestNSSDB) {
+  if (!test_db_->is_open())
+    return;
+  SetSystemKeySlotForTesting(
+      ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot())));
+}
+
+ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() {
+  SetSystemKeySlotForTesting(ScopedPK11Slot());
+}
+
+bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const {
+  return test_db_->is_open();
+}
+
+}  // namespace crypto
diff --git a/crypto/scoped_test_system_nss_key_slot.h b/crypto/scoped_test_system_nss_key_slot.h
new file mode 100644
index 0000000..1565047
--- /dev/null
+++ b/crypto/scoped_test_system_nss_key_slot.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
+#define CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+class ScopedTestNSSDB;
+
+// Opens a persistent NSS software database in a temporary directory and sets
+// the test system slot to the opened database. This helper should be created in
+// tests where no system token is provided by the Chaps module and before
+// InitializeTPMTokenAndSystemSlot is called. Then the opened test database will
+// be used and the initialization continues as if Chaps had provided this test
+// database. In particular, the DB will be exposed by |GetSystemNSSKeySlot| and
+// |IsTPMTokenReady| will return true.
+// At most one instance of this helper must be used at a time.
+class CRYPTO_EXPORT_PRIVATE ScopedTestSystemNSSKeySlot {
+ public:
+  explicit ScopedTestSystemNSSKeySlot();
+  ~ScopedTestSystemNSSKeySlot();
+
+  bool ConstructedSuccessfully() const;
+
+ private:
+  scoped_ptr<ScopedTestNSSDB> test_db_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTestSystemNSSKeySlot);
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 0956bfb..9d36de8 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1085,6 +1085,7 @@
     "//base/third_party/dynamic_annotations",
     "//crypto",
     "//crypto:platform",
+    "//crypto:test_support",
     "//net/base/registry_controlled_domains",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/net/base/keygen_handler_unittest.cc b/net/base/keygen_handler_unittest.cc
index 2cb64743..2962330 100644
--- a/net/base/keygen_handler_unittest.cc
+++ b/net/base/keygen_handler_unittest.cc
@@ -19,8 +19,7 @@
 #if defined(USE_NSS)
 #include <private/pprthred.h>  // PR_DetachThread
 #include "crypto/nss_crypto_module_delegate.h"
-#include "crypto/nss_util.h"
-#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_db.h"
 #endif
 
 namespace net {
@@ -59,8 +58,8 @@
 #if defined(USE_NSS)
     handler->set_crypto_module_delegate(
         scoped_ptr<crypto::NSSCryptoModuleDelegate>(
-            new StubCryptoModuleDelegate(
-                crypto::ScopedPK11Slot(crypto::GetPersistentNSSKeySlot()))));
+            new StubCryptoModuleDelegate(crypto::ScopedPK11Slot(
+                PK11_ReferenceSlot(test_nss_db_.slot())))));
 #endif
     return handler.Pass();
   }
diff --git a/net/cert/nss_cert_database_chromeos_unittest.cc b/net/cert/nss_cert_database_chromeos_unittest.cc
index 324575d0..900edad 100644
--- a/net/cert/nss_cert_database_chromeos_unittest.cc
+++ b/net/cert/nss_cert_database_chromeos_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/callback.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/run_loop.h"
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/test_data_directory.h"
 #include "net/cert/cert_database.h"
 #include "net/test/cert_test_util.h"
diff --git a/net/cert/nss_cert_database_unittest.cc b/net/cert/nss_cert_database_unittest.cc
index 71e1264..ffa61744 100644
--- a/net/cert/nss_cert_database_unittest.cc
+++ b/net/cert/nss_cert_database_unittest.cc
@@ -19,9 +19,8 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "crypto/nss_util.h"
-#include "crypto/nss_util_internal.h"
 #include "crypto/scoped_nss_types.h"
+#include "crypto/scoped_test_nss_db.h"
 #include "net/base/crypto_module.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_data_directory.h"
@@ -59,8 +58,10 @@
   virtual void SetUp() {
     ASSERT_TRUE(test_nssdb_.is_open());
     cert_db_.reset(new NSSCertDatabase(
-        crypto::ScopedPK11Slot(crypto::GetPersistentNSSKeySlot()),
-        crypto::ScopedPK11Slot(crypto::GetPersistentNSSKeySlot())));
+        crypto::ScopedPK11Slot(
+            PK11_ReferenceSlot(test_nssdb_.slot())) /* public slot */,
+        crypto::ScopedPK11Slot(
+            PK11_ReferenceSlot(test_nssdb_.slot())) /* private slot */));
     public_module_ = cert_db_->GetPublicModule();
 
     // Test db should be empty at start of test.
@@ -99,9 +100,7 @@
 
   CertificateList ListCerts() {
     CertificateList result;
-
-    CERTCertList* cert_list =
-        PK11_ListCertsInSlot(cert_db_->GetPublicSlot().get());
+    CERTCertList* cert_list = PK11_ListCertsInSlot(test_nssdb_.slot());
     for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
          !CERT_LIST_END(node, cert_list);
          node = CERT_LIST_NEXT(node)) {
diff --git a/net/cert/nss_profile_filter_chromeos_unittest.cc b/net/cert/nss_profile_filter_chromeos_unittest.cc
index 60ceeb1..b133c33 100644
--- a/net/cert/nss_profile_filter_chromeos_unittest.cc
+++ b/net/cert/nss_profile_filter_chromeos_unittest.cc
@@ -8,9 +8,9 @@
 #include <pk11pub.h>
 #include <secmod.h>
 
-#include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
 #include "crypto/scoped_nss_types.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/test_data_directory.h"
 #include "net/test/cert_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/net.gyp b/net/net.gyp
index c88ad52..f9f55cf8 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -537,6 +537,7 @@
         '../base/base.gyp:base_prefs_test_support',
         '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
         '../crypto/crypto.gyp:crypto',
+        '../crypto/crypto.gyp:crypto_test_support',
         '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
         '../third_party/zlib/zlib.gyp:zlib',
diff --git a/net/ssl/client_cert_store_chromeos_unittest.cc b/net/ssl/client_cert_store_chromeos_unittest.cc
index 4a6a6c35..3bd6d60 100644
--- a/net/ssl/client_cert_store_chromeos_unittest.cc
+++ b/net/ssl/client_cert_store_chromeos_unittest.cc
@@ -13,6 +13,7 @@
 #include "crypto/nss_util.h"
 #include "crypto/nss_util_internal.h"
 #include "crypto/rsa_private_key.h"
+#include "crypto/scoped_test_nss_chromeos_user.h"
 #include "net/base/test_data_directory.h"
 #include "net/cert/cert_type.h"
 #include "net/cert/x509_certificate.h"