1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// Copyright 2013 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 "chrome/browser/net/nss_context.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "chrome/browser/chromeos/login/login_manager_test.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
#include "net/cert/nss_cert_database.h"
namespace {
const char kTestUser1[] = "test-user1@gmail.com";
const char kTestUser2[] = "test-user2@gmail.com";
void NotCalledDbCallback(net::NSSCertDatabase* db) { ASSERT_TRUE(false); }
// DBTester handles retrieving the NSSCertDatabase for a given profile, and
// doing some simple sanity checks.
// Browser test cases run on the UI thread, while the nss_context access needs
// to happen on the IO thread. The DBTester class encapsulates the thread
// posting and waiting on the UI thread so that the test case body can be
// written linearly.
class DBTester {
public:
explicit DBTester(Profile* profile) : profile_(profile), db_(NULL) {}
// Initial retrieval of cert database. It may be asynchronous or synchronous.
// Returns true if the database was retrieved successfully.
bool DoGetDBTests() {
base::RunLoop run_loop;
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
base::Bind(&DBTester::GetDBAndDoTestsOnIOThread,
base::Unretained(this),
profile_->GetResourceContext(),
run_loop.QuitClosure()));
run_loop.Run();
return !!db_;
}
// Test retrieving the database again, should be called after DoGetDBTests.
void DoGetDBAgainTests() {
base::RunLoop run_loop;
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
base::Bind(&DBTester::DoGetDBAgainTestsOnIOThread,
base::Unretained(this),
profile_->GetResourceContext(),
run_loop.QuitClosure()));
run_loop.Run();
}
void DoNotEqualsTests(DBTester* other_tester) {
// The DB and its NSS slots should be different for each profile.
EXPECT_NE(db_, other_tester->db_);
EXPECT_NE(db_->GetPublicSlot().get(),
other_tester->db_->GetPublicSlot().get());
}
private:
void GetDBAndDoTestsOnIOThread(content::ResourceContext* context,
const base::Closure& done_callback) {
net::NSSCertDatabase* db = GetNSSCertDatabaseForResourceContext(
context,
base::Bind(&DBTester::DoTestsOnIOThread,
base::Unretained(this),
done_callback));
if (db) {
DVLOG(1) << "got db synchronously";
DoTestsOnIOThread(done_callback, db);
} else {
DVLOG(1) << "getting db asynchronously...";
}
}
void DoTestsOnIOThread(const base::Closure& done_callback,
net::NSSCertDatabase* db) {
db_ = db;
EXPECT_TRUE(db);
if (db) {
EXPECT_TRUE(db->GetPublicSlot().get());
// Public and private slot are the same in tests.
EXPECT_EQ(db->GetPublicSlot().get(), db->GetPrivateSlot().get());
}
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE, done_callback);
}
void DoGetDBAgainTestsOnIOThread(content::ResourceContext* context,
const base::Closure& done_callback) {
net::NSSCertDatabase* db = GetNSSCertDatabaseForResourceContext(
context, base::Bind(&NotCalledDbCallback));
// Should always be synchronous now.
EXPECT_TRUE(db);
// Should return the same db as before.
EXPECT_EQ(db_, db);
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE, done_callback);
}
Profile* profile_;
net::NSSCertDatabase* db_;
};
} // namespace
class NSSContextChromeOSBrowserTest : public chromeos::LoginManagerTest {
public:
NSSContextChromeOSBrowserTest()
: LoginManagerTest(true /* should_launch_browser */) {}
virtual ~NSSContextChromeOSBrowserTest() {}
};
IN_PROC_BROWSER_TEST_F(NSSContextChromeOSBrowserTest, PRE_TwoUsers) {
// Initialization for ChromeOS multi-profile test infrastructure.
RegisterUser(kTestUser1);
RegisterUser(kTestUser2);
chromeos::StartupUtils::MarkOobeCompleted();
}
IN_PROC_BROWSER_TEST_F(NSSContextChromeOSBrowserTest, TwoUsers) {
user_manager::UserManager* user_manager = user_manager::UserManager::Get();
// Log in first user and get their DB.
LoginUser(kTestUser1);
Profile* profile1 = chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(
user_manager->FindUser(kTestUser1));
ASSERT_TRUE(profile1);
DBTester tester1(profile1);
ASSERT_TRUE(tester1.DoGetDBTests());
// Log in second user and get their DB.
chromeos::UserAddingScreen::Get()->Start();
base::RunLoop().RunUntilIdle();
AddUser(kTestUser2);
Profile* profile2 = chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(
user_manager->FindUser(kTestUser2));
ASSERT_TRUE(profile2);
DBTester tester2(profile2);
ASSERT_TRUE(tester2.DoGetDBTests());
// Get both DBs again to check that the same object is returned.
tester1.DoGetDBAgainTests();
tester2.DoGetDBAgainTests();
// Check that each user has a separate DB and NSS slots.
tester1.DoNotEqualsTests(&tester2);
}
|