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