1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/website_settings/website_settings.h"
7 #include "base/at_exit.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/ui/website_settings/website_settings_ui.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "components/content_settings/core/browser/host_content_settings_map.h"
16 #include "components/content_settings/core/common/content_settings.h"
17 #include "components/content_settings/core/common/content_settings_types.h"
18 #include "components/infobars/core/infobar.h"
19 #include "content/public/browser/cert_store.h"
20 #include "content/public/common/ssl_status.h"
21 #include "net/cert/cert_status_flags.h"
22 #include "net/cert/x509_certificate.h"
23 #include "net/ssl/ssl_connection_status_flags.h"
24 #include "net/test/test_certificate_data.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using content::SSLStatus;
30 using testing::AnyNumber;
31 using testing::Return;
32 using testing::SetArgPointee;
36 // SSL cipher suite like specified in RFC5246 Appendix A.5. "The Cipher Suite".
37 // Without the CR_ prefix, this clashes with the OS X 10.8 headers.
38 int CR_TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3D;
40 int SetSSLVersion(int connection_status, int version) {
41 // Clear SSL version bits (Bits 20, 21 and 22).
43 ~(net::SSL_CONNECTION_VERSION_MASK << net::SSL_CONNECTION_VERSION_SHIFT);
44 int bitmask = version << net::SSL_CONNECTION_VERSION_SHIFT;
45 return bitmask | connection_status;
48 int SetSSLCipherSuite(int connection_status, int cipher_suite) {
49 // Clear cipher suite bits (the 16 lowest bits).
50 connection_status &= ~net::SSL_CONNECTION_CIPHERSUITE_MASK;
51 return cipher_suite | connection_status;
54 class MockCertStore : public content::CertStore {
56 virtual ~MockCertStore() {}
57 MOCK_METHOD2(StoreCert, int(net::X509Certificate*, int));
58 MOCK_METHOD2(RetrieveCert, bool(int, scoped_refptr<net::X509Certificate>*));
61 class MockWebsiteSettingsUI : public WebsiteSettingsUI {
63 virtual ~MockWebsiteSettingsUI() {}
64 MOCK_METHOD1(SetCookieInfo, void(const CookieInfoList& cookie_info_list));
65 MOCK_METHOD1(SetPermissionInfo,
66 void(const PermissionInfoList& permission_info_list));
67 MOCK_METHOD1(SetIdentityInfo, void(const IdentityInfo& identity_info));
68 MOCK_METHOD1(SetFirstVisit, void(const base::string16& first_visit));
69 MOCK_METHOD1(SetSelectedTab, void(TabId tab_id));
72 class WebsiteSettingsTest : public ChromeRenderViewHostTestHarness {
74 WebsiteSettingsTest() : cert_id_(0), url_("http://www.example.com") {}
76 ~WebsiteSettingsTest() override {}
78 void SetUp() override {
79 ChromeRenderViewHostTestHarness::SetUp();
80 // Setup stub SSLStatus.
81 ssl_.security_style = content::SECURITY_STYLE_UNAUTHENTICATED;
83 // Create the certificate.
85 base::Time start_date = base::Time::Now();
86 base::Time expiration_date = base::Time::FromInternalValue(
87 start_date.ToInternalValue() + base::Time::kMicrosecondsPerWeek);
88 cert_ = new net::X509Certificate("subject",
93 TabSpecificContentSettings::CreateForWebContents(web_contents());
94 InfoBarService::CreateForWebContents(web_contents());
96 // Setup the mock cert store.
97 EXPECT_CALL(cert_store_, RetrieveCert(cert_id_, _) )
99 .WillRepeatedly(DoAll(SetArgPointee<1>(cert_), Return(true)));
102 mock_ui_.reset(new MockWebsiteSettingsUI());
105 void TearDown() override {
106 ASSERT_TRUE(website_settings_.get())
107 << "No WebsiteSettings instance created.";
108 RenderViewHostTestHarness::TearDown();
109 website_settings_.reset();
112 void SetDefaultUIExpectations(MockWebsiteSettingsUI* mock_ui) {
113 // During creation |WebsiteSettings| makes the following calls to the ui.
114 EXPECT_CALL(*mock_ui, SetPermissionInfo(_));
115 EXPECT_CALL(*mock_ui, SetIdentityInfo(_));
116 EXPECT_CALL(*mock_ui, SetCookieInfo(_));
117 EXPECT_CALL(*mock_ui, SetFirstVisit(base::string16()));
120 void SetURL(std::string url) { url_ = GURL(url); }
122 const GURL& url() const { return url_; }
123 MockCertStore* cert_store() { return &cert_store_; }
124 int cert_id() { return cert_id_; }
125 MockWebsiteSettingsUI* mock_ui() { return mock_ui_.get(); }
126 const SSLStatus& ssl() { return ssl_; }
127 TabSpecificContentSettings* tab_specific_content_settings() {
128 return TabSpecificContentSettings::FromWebContents(web_contents());
130 InfoBarService* infobar_service() {
131 return InfoBarService::FromWebContents(web_contents());
134 WebsiteSettings* website_settings() {
135 if (!website_settings_.get()) {
136 website_settings_.reset(new WebsiteSettings(
137 mock_ui(), profile(), tab_specific_content_settings(),
138 infobar_service(), url(), ssl(), cert_store()));
140 return website_settings_.get();
146 scoped_ptr<WebsiteSettings> website_settings_;
147 scoped_ptr<MockWebsiteSettingsUI> mock_ui_;
149 scoped_refptr<net::X509Certificate> cert_;
150 MockCertStore cert_store_;
156 TEST_F(WebsiteSettingsTest, OnPermissionsChanged) {
157 // Setup site permissions.
158 HostContentSettingsMap* content_settings =
159 profile()->GetHostContentSettingsMap();
160 ContentSetting setting = content_settings->GetContentSetting(
161 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS, std::string());
162 EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
163 setting = content_settings->GetContentSetting(
164 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS, std::string());
165 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
166 setting = content_settings->GetContentSetting(
167 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string());
168 EXPECT_EQ(setting, CONTENT_SETTING_ASK);
169 setting = content_settings->GetContentSetting(
170 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string());
171 EXPECT_EQ(setting, CONTENT_SETTING_ASK);
172 setting = content_settings->GetContentSetting(
173 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string());
174 EXPECT_EQ(setting, CONTENT_SETTING_ASK);
175 setting = content_settings->GetContentSetting(
176 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string());
177 EXPECT_EQ(setting, CONTENT_SETTING_ASK);
179 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_));
180 EXPECT_CALL(*mock_ui(), SetCookieInfo(_));
181 EXPECT_CALL(*mock_ui(), SetFirstVisit(base::string16()));
183 // SetPermissionInfo() is called once initially, and then again every time
184 // OnSitePermissionChanged() is called.
185 // TODO(markusheintz): This is a temporary hack to fix issue: http://crbug.com/144203.
186 #if defined(OS_MACOSX)
187 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_)).Times(6);
189 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_)).Times(1);
191 EXPECT_CALL(*mock_ui(), SetSelectedTab(
192 WebsiteSettingsUI::TAB_ID_PERMISSIONS));
194 // Execute code under tests.
195 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_POPUPS,
196 CONTENT_SETTING_ALLOW);
197 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_PLUGINS,
198 CONTENT_SETTING_BLOCK);
199 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_GEOLOCATION,
200 CONTENT_SETTING_ALLOW);
201 website_settings()->OnSitePermissionChanged(
202 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW);
203 website_settings()->OnSitePermissionChanged(
204 CONTENT_SETTINGS_TYPE_MEDIASTREAM, CONTENT_SETTING_ALLOW);
206 // Verify that the site permissions were changed correctly.
207 setting = content_settings->GetContentSetting(
208 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS, std::string());
209 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
210 setting = content_settings->GetContentSetting(
211 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS, std::string());
212 EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
213 setting = content_settings->GetContentSetting(
214 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string());
215 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
216 setting = content_settings->GetContentSetting(
217 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string());
218 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
219 setting = content_settings->GetContentSetting(
220 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string());
221 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
222 setting = content_settings->GetContentSetting(
223 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string());
224 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
227 TEST_F(WebsiteSettingsTest, OnSiteDataAccessed) {
228 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_));
229 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_));
230 EXPECT_CALL(*mock_ui(), SetFirstVisit(base::string16()));
231 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)).Times(2);
232 EXPECT_CALL(*mock_ui(), SetSelectedTab(
233 WebsiteSettingsUI::TAB_ID_PERMISSIONS));
235 website_settings()->OnSiteDataAccessed();
238 TEST_F(WebsiteSettingsTest, HTTPConnection) {
239 SetDefaultUIExpectations(mock_ui());
240 EXPECT_CALL(*mock_ui(), SetSelectedTab(
241 WebsiteSettingsUI::TAB_ID_PERMISSIONS));
242 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED,
243 website_settings()->site_connection_status());
244 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_NO_CERT,
245 website_settings()->site_identity_status());
246 EXPECT_EQ(base::string16(), website_settings()->organization_name());
249 TEST_F(WebsiteSettingsTest, HTTPSConnection) {
250 ssl_.security_style = content::SECURITY_STYLE_AUTHENTICATED;
251 ssl_.cert_id = cert_id();
252 ssl_.cert_status = 0;
253 ssl_.security_bits = 81; // No error if > 80.
255 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1);
256 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256);
257 ssl_.connection_status = status;
259 SetDefaultUIExpectations(mock_ui());
260 EXPECT_CALL(*mock_ui(), SetSelectedTab(
261 WebsiteSettingsUI::TAB_ID_PERMISSIONS));
263 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED,
264 website_settings()->site_connection_status());
265 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT,
266 website_settings()->site_identity_status());
267 EXPECT_EQ(base::string16(), website_settings()->organization_name());
270 TEST_F(WebsiteSettingsTest, HTTPSMixedContent) {
271 ssl_.security_style = content::SECURITY_STYLE_AUTHENTICATED;
272 ssl_.cert_id = cert_id();
273 ssl_.cert_status = 0;
274 ssl_.security_bits = 81; // No error if > 80.
275 ssl_.content_status = SSLStatus::DISPLAYED_INSECURE_CONTENT;
277 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1);
278 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256);
279 ssl_.connection_status = status;
281 SetDefaultUIExpectations(mock_ui());
282 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
284 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_MIXED_CONTENT,
285 website_settings()->site_connection_status());
286 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT,
287 website_settings()->site_identity_status());
288 EXPECT_EQ(base::string16(), website_settings()->organization_name());
291 TEST_F(WebsiteSettingsTest, HTTPSEVCert) {
292 scoped_refptr<net::X509Certificate> ev_cert =
293 net::X509Certificate::CreateFromBytes(
294 reinterpret_cast<const char*>(google_der),
297 EXPECT_CALL(*cert_store(), RetrieveCert(ev_cert_id, _)).WillRepeatedly(
298 DoAll(SetArgPointee<1>(ev_cert), Return(true)));
300 ssl_.security_style = content::SECURITY_STYLE_AUTHENTICATED;
301 ssl_.cert_id = ev_cert_id;
302 ssl_.cert_status = net::CERT_STATUS_IS_EV;
303 ssl_.security_bits = 81; // No error if > 80.
304 ssl_.content_status = SSLStatus::DISPLAYED_INSECURE_CONTENT;
306 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1);
307 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256);
308 ssl_.connection_status = status;
310 SetDefaultUIExpectations(mock_ui());
311 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
313 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_MIXED_CONTENT,
314 website_settings()->site_connection_status());
315 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT,
316 website_settings()->site_identity_status());
317 EXPECT_EQ(base::UTF8ToUTF16("Google Inc"),
318 website_settings()->organization_name());
321 TEST_F(WebsiteSettingsTest, HTTPSRevocationError) {
322 ssl_.security_style = content::SECURITY_STYLE_AUTHENTICATED;
323 ssl_.cert_id = cert_id();
324 ssl_.cert_status = net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
325 ssl_.security_bits = 81; // No error if > 80.
327 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1);
328 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256);
329 ssl_.connection_status = status;
331 SetDefaultUIExpectations(mock_ui());
332 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
334 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED,
335 website_settings()->site_connection_status());
336 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN,
337 website_settings()->site_identity_status());
338 EXPECT_EQ(base::string16(), website_settings()->organization_name());
341 TEST_F(WebsiteSettingsTest, HTTPSConnectionError) {
342 ssl_.security_style = content::SECURITY_STYLE_AUTHENTICATED;
343 ssl_.cert_id = cert_id();
344 ssl_.cert_status = 0;
345 ssl_.security_bits = 1;
347 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1);
348 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256);
349 ssl_.connection_status = status;
351 SetDefaultUIExpectations(mock_ui());
352 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
354 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR,
355 website_settings()->site_connection_status());
356 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT,
357 website_settings()->site_identity_status());
358 EXPECT_EQ(base::string16(), website_settings()->organization_name());
361 TEST_F(WebsiteSettingsTest, NoInfoBar) {
362 SetDefaultUIExpectations(mock_ui());
363 EXPECT_CALL(*mock_ui(), SetSelectedTab(
364 WebsiteSettingsUI::TAB_ID_PERMISSIONS));
365 EXPECT_EQ(0u, infobar_service()->infobar_count());
366 website_settings()->OnUIClosing();
367 EXPECT_EQ(0u, infobar_service()->infobar_count());
370 TEST_F(WebsiteSettingsTest, ShowInfoBar) {
371 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_));
372 EXPECT_CALL(*mock_ui(), SetCookieInfo(_));
373 EXPECT_CALL(*mock_ui(), SetFirstVisit(base::string16()));
375 // SetPermissionInfo() is called once initially, and then again every time
376 // OnSitePermissionChanged() is called.
377 // TODO(markusheintz): This is a temporary hack to fix issue:
378 // http://crbug.com/144203.
379 #if defined(OS_MACOSX)
380 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_)).Times(2);
382 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_)).Times(1);
385 EXPECT_CALL(*mock_ui(), SetSelectedTab(
386 WebsiteSettingsUI::TAB_ID_PERMISSIONS));
387 EXPECT_EQ(0u, infobar_service()->infobar_count());
388 website_settings()->OnSitePermissionChanged(
389 CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTING_ALLOW);
390 website_settings()->OnUIClosing();
391 ASSERT_EQ(1u, infobar_service()->infobar_count());
393 infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));
396 TEST_F(WebsiteSettingsTest, AboutBlankPage) {
397 SetURL("about:blank");
398 SetDefaultUIExpectations(mock_ui());
399 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE,
400 website_settings()->site_connection_status());
401 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_INTERNAL_PAGE,
402 website_settings()->site_identity_status());
403 EXPECT_EQ(base::string16(), website_settings()->organization_name());
406 TEST_F(WebsiteSettingsTest, InternalPage) {
407 SetURL("chrome://bookmarks");
408 SetDefaultUIExpectations(mock_ui());
409 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE,
410 website_settings()->site_connection_status());
411 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_INTERNAL_PAGE,
412 website_settings()->site_identity_status());
413 EXPECT_EQ(base::string16(), website_settings()->organization_name());