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