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 "base/callback.h"
6#include "base/values.h"
7#include "chrome/browser/browser_process.h"
8#include "chrome/browser/ui/browser.h"
9#include "chrome/browser/ui/tabs/tab_strip_model.h"
10#include "chrome/browser/ui/webui/options/options_ui_browsertest.h"
11#include "chrome/common/url_constants.h"
12#include "components/policy/core/browser/browser_policy_connector.h"
13#include "components/policy/core/common/external_data_fetcher.h"
14#include "components/policy/core/common/mock_configuration_policy_provider.h"
15#include "components/policy/core/common/policy_map.h"
16#include "components/policy/core/common/policy_types.h"
17#include "content/public/browser/render_frame_host.h"
18#include "content/public/browser/web_contents.h"
19#include "content/public/test/browser_test_utils.h"
20#include "content/public/test/test_utils.h"
21#include "policy/policy_constants.h"
22#include "testing/gmock/include/gmock/gmock.h"
23#include "testing/gtest/include/gtest/gtest.h"
24
25#if defined(OS_CHROMEOS)
26#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
27#include "chrome/browser/chromeos/policy/user_network_configuration_updater.h"
28#include "chrome/browser/chromeos/policy/user_network_configuration_updater_factory.h"
29#include "chrome/browser/net/nss_context.h"
30#include "chromeos/network/onc/onc_certificate_importer_impl.h"
31#include "chromeos/network/onc/onc_test_utils.h"
32#include "crypto/nss_util.h"
33#endif
34
35using testing::Return;
36using testing::_;
37
38class CertificateManagerBrowserTest : public options::OptionsUIBrowserTest {
39 public:
40  CertificateManagerBrowserTest() {}
41  virtual ~CertificateManagerBrowserTest() {}
42
43 protected:
44  virtual void SetUp() OVERRIDE {
45#if defined(OS_CHROMEOS)
46    policy::UserNetworkConfigurationUpdater::
47        SetSkipCertificateImporterCreationForTest(true);
48#endif
49    options::OptionsUIBrowserTest::SetUp();
50  }
51
52  virtual void TearDown() OVERRIDE {
53#if defined(OS_CHROMEOS)
54    policy::UserNetworkConfigurationUpdater::
55        SetSkipCertificateImporterCreationForTest(false);
56#endif
57    options::OptionsUIBrowserTest::TearDown();
58  }
59
60  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
61#if defined(OS_CHROMEOS)
62    device_policy_test_helper_.MarkAsEnterpriseOwned();
63#endif
64    // Setup the policy provider for injecting certs through ONC policy.
65    EXPECT_CALL(provider_, IsInitializationComplete(_))
66        .WillRepeatedly(Return(true));
67    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
68  }
69
70  void SetUpOnIOThread() {
71#if defined(OS_CHROMEOS)
72    test_nssdb_.reset(new crypto::ScopedTestNSSDB());
73#endif
74  }
75
76  void TearDownOnIOThread() {
77#if defined(OS_CHROMEOS)
78    test_nssdb_.reset();
79#endif
80  }
81
82  virtual void SetUpOnMainThread() OVERRIDE {
83    content::BrowserThread::PostTask(
84        content::BrowserThread::IO,
85        FROM_HERE,
86        base::Bind(&CertificateManagerBrowserTest::SetUpOnIOThread, this));
87
88    content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
89    content::RunAllPendingInMessageLoop();
90
91#if defined(OS_CHROMEOS)
92    // UserNetworkConfigurationUpdater's onc::CertificateImporter is usually
93    // passed the NSSCertDatabase fetched during testing profile
94    // constrution. Unfortunately, test database gets setup after that, so we
95    // would end up with |PK11_GetInternalKeySlot|. The cause of this is in
96    // |crypto::InitializeNSSForChromeOSUser|, which does not open new
97    // database slot for primary user, but it just uses the singleton one (which
98    // is not set in tests before |test_nssdb_| is created). To handle this,
99    // creating certificate importer during the UserNetworkConfiguirationUpdater
100    // service creation is set to be skipped (see |SetUp|), and cert importer
101    // is set up here.
102    // Note that creating |test_nssdb_| sooner (in SetUp) would break thread
103    // restrictions, which require it to be used on IO thread only.
104    // TODO(tbarzic): Update InitializeNSSForChromeOSUser not to special case
105    // the primary user.
106    GetNSSCertDatabaseForProfile(
107        browser()->profile(),
108        base::Bind(
109            &CertificateManagerBrowserTest::UpdateNetworkConfigurationUpdater,
110            base::Unretained(this)));
111
112    content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
113    content::RunAllPendingInMessageLoop();
114#endif
115  }
116
117  virtual void CleanUpOnMainThread() OVERRIDE {
118    content::BrowserThread::PostTask(
119        content::BrowserThread::IO,
120        FROM_HERE,
121        base::Bind(&CertificateManagerBrowserTest::TearDownOnIOThread, this));
122    content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
123  }
124
125#if defined(OS_CHROMEOS)
126  void UpdateNetworkConfigurationUpdater(net::NSSCertDatabase* database) {
127    policy::UserNetworkConfigurationUpdaterFactory::GetForProfile(
128        browser()->profile())->SetCertificateImporterForTest(
129            scoped_ptr<chromeos::onc::CertificateImporter>(
130                new chromeos::onc::CertificateImporterImpl(database)));
131  }
132
133  void LoadONCPolicy(const std::string& filename) {
134    const std::string& user_policy_blob =
135        chromeos::onc::test_utils::ReadTestData(filename);
136    policy::PolicyMap policy;
137    policy.Set(policy::key::kOpenNetworkConfiguration,
138               policy::POLICY_LEVEL_MANDATORY,
139               policy::POLICY_SCOPE_USER,
140               base::Value::CreateStringValue(user_policy_blob),
141               NULL);
142    provider_.UpdateChromePolicy(policy);
143    content::RunAllPendingInMessageLoop();
144  }
145#endif
146
147  void ClickElement(const std::string& selector) {
148    EXPECT_TRUE(content::ExecuteScript(
149        GetSettingsFrame(),
150        "document.querySelector(\"" + selector + "\").click()"));
151  }
152
153  bool HasElement(const std::string& selector) {
154    bool result;
155    EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
156        GetSettingsFrame(),
157        "window.domAutomationController.send("
158        "    !!document.querySelector('" + selector + "'));",
159        &result));
160    return result;
161  }
162
163  policy::MockConfigurationPolicyProvider provider_;
164#if defined(OS_CHROMEOS)
165  policy::DevicePolicyCrosTestHelper device_policy_test_helper_;
166  scoped_ptr<crypto::ScopedTestNSSDB> test_nssdb_;
167#endif
168};
169
170#if defined(OS_CHROMEOS)
171// Ensure policy-installed certificates without web trust do not display
172// the managed setting indicator (only on Chrome OS).
173IN_PROC_BROWSER_TEST_F(CertificateManagerBrowserTest,
174                       PolicyCertificateWithoutWebTrustHasNoIndicator) {
175  LoadONCPolicy("certificate-authority.onc");
176  NavigateToSettings();
177  ClickElement("#certificatesManageButton");
178  ClickElement("#ca-certs-nav-tab");
179  EXPECT_FALSE(HasElement(".cert-policy"));
180}
181#endif
182
183#if defined(OS_CHROMEOS)
184// Ensure policy-installed certificates with web trust display the
185// managed setting indicator (only on Chrome OS).
186IN_PROC_BROWSER_TEST_F(CertificateManagerBrowserTest,
187                       PolicyCertificateWithWebTrustHasIndicator) {
188  LoadONCPolicy("certificate-web-authority.onc");
189  NavigateToSettings();
190  ClickElement("#certificatesManageButton");
191  ClickElement("#ca-certs-nav-tab");
192  EXPECT_TRUE(HasElement(".cert-policy"));
193}
194#endif
195