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/content_settings/content_settings_provider.h"
12 #include "chrome/browser/content_settings/content_settings_utils.h"
13 #include "chrome/browser/content_settings/host_content_settings_map.h"
14 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
15 #include "chrome/browser/infobars/infobar.h"
16 #include "chrome/browser/infobars/infobar_service.h"
17 #include "chrome/browser/ui/website_settings/website_settings_ui.h"
18 #include "chrome/common/content_settings.h"
19 #include "chrome/common/content_settings_types.h"
20 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "content/public/browser/cert_store.h"
23 #include "content/public/common/ssl_status.h"
24 #include "net/cert/cert_status_flags.h"
25 #include "net/cert/x509_certificate.h"
26 #include "net/ssl/ssl_connection_status_flags.h"
27 #include "net/test/test_certificate_data.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 using content::SSLStatus
;
33 using testing::AnyNumber
;
34 using testing::Return
;
35 using testing::SetArgPointee
;
39 // SSL cipher suite like specified in RFC5246 Appendix A.5. "The Cipher Suite".
40 // Without the CR_ prefix, this clashes with the OS X 10.8 headers.
41 int CR_TLS_RSA_WITH_AES_256_CBC_SHA256
= 0x3D;
43 int SetSSLVersion(int connection_status
, int version
) {
44 // Clear SSL version bits (Bits 20, 21 and 22).
46 ~(net::SSL_CONNECTION_VERSION_MASK
<< net::SSL_CONNECTION_VERSION_SHIFT
);
47 int bitmask
= version
<< net::SSL_CONNECTION_VERSION_SHIFT
;
48 return bitmask
| connection_status
;
51 int SetSSLCipherSuite(int connection_status
, int cipher_suite
) {
52 // Clear cipher suite bits (the 16 lowest bits).
53 connection_status
&= ~net::SSL_CONNECTION_CIPHERSUITE_MASK
;
54 return cipher_suite
| connection_status
;
57 class MockCertStore
: public content::CertStore
{
59 virtual ~MockCertStore() {}
60 MOCK_METHOD2(StoreCert
, int(net::X509Certificate
*, int));
61 MOCK_METHOD2(RetrieveCert
, bool(int, scoped_refptr
<net::X509Certificate
>*));
64 class MockWebsiteSettingsUI
: public WebsiteSettingsUI
{
66 virtual ~MockWebsiteSettingsUI() {}
67 MOCK_METHOD1(SetCookieInfo
, void(const CookieInfoList
& cookie_info_list
));
68 MOCK_METHOD1(SetPermissionInfo
,
69 void(const PermissionInfoList
& permission_info_list
));
70 MOCK_METHOD1(SetIdentityInfo
, void(const IdentityInfo
& identity_info
));
71 MOCK_METHOD1(SetFirstVisit
, void(const base::string16
& first_visit
));
72 MOCK_METHOD1(SetSelectedTab
, void(TabId tab_id
));
75 class WebsiteSettingsTest
: public ChromeRenderViewHostTestHarness
{
77 WebsiteSettingsTest() : cert_id_(0), url_("http://www.example.com") {}
79 virtual ~WebsiteSettingsTest() {
82 virtual void SetUp() {
83 ChromeRenderViewHostTestHarness::SetUp();
84 // Setup stub SSLStatus.
85 ssl_
.security_style
= content::SECURITY_STYLE_UNAUTHENTICATED
;
87 // Create the certificate.
89 base::Time start_date
= base::Time::Now();
90 base::Time expiration_date
= base::Time::FromInternalValue(
91 start_date
.ToInternalValue() + base::Time::kMicrosecondsPerWeek
);
92 cert_
= new net::X509Certificate("subject",
97 TabSpecificContentSettings::CreateForWebContents(web_contents());
98 InfoBarService::CreateForWebContents(web_contents());
100 // Setup the mock cert store.
101 EXPECT_CALL(cert_store_
, RetrieveCert(cert_id_
, _
) )
103 .WillRepeatedly(DoAll(SetArgPointee
<1>(cert_
), Return(true)));
106 mock_ui_
.reset(new MockWebsiteSettingsUI());
109 virtual void TearDown() {
110 ASSERT_TRUE(website_settings_
.get())
111 << "No WebsiteSettings instance created.";
112 RenderViewHostTestHarness::TearDown();
113 website_settings_
.reset();
116 void SetDefaultUIExpectations(MockWebsiteSettingsUI
* mock_ui
) {
117 // During creation |WebsiteSettings| makes the following calls to the ui.
118 EXPECT_CALL(*mock_ui
, SetPermissionInfo(_
));
119 EXPECT_CALL(*mock_ui
, SetIdentityInfo(_
));
120 EXPECT_CALL(*mock_ui
, SetCookieInfo(_
));
121 EXPECT_CALL(*mock_ui
, SetFirstVisit(base::string16()));
124 const GURL
& url() const { return url_
; }
125 MockCertStore
* cert_store() { return &cert_store_
; }
126 int cert_id() { return cert_id_
; }
127 MockWebsiteSettingsUI
* mock_ui() { return mock_ui_
.get(); }
128 const SSLStatus
& ssl() { return ssl_
; }
129 TabSpecificContentSettings
* tab_specific_content_settings() {
130 return TabSpecificContentSettings::FromWebContents(web_contents());
132 InfoBarService
* infobar_service() {
133 return InfoBarService::FromWebContents(web_contents());
136 WebsiteSettings
* website_settings() {
137 if (!website_settings_
.get()) {
138 website_settings_
.reset(new WebsiteSettings(
139 mock_ui(), profile(), tab_specific_content_settings(),
140 infobar_service(), url(), ssl(), cert_store()));
142 return website_settings_
.get();
148 scoped_ptr
<WebsiteSettings
> website_settings_
;
149 scoped_ptr
<MockWebsiteSettingsUI
> mock_ui_
;
151 scoped_refptr
<net::X509Certificate
> cert_
;
152 MockCertStore cert_store_
;
158 TEST_F(WebsiteSettingsTest
, OnPermissionsChanged
) {
159 // Setup site permissions.
160 HostContentSettingsMap
* content_settings
=
161 profile()->GetHostContentSettingsMap();
162 ContentSetting setting
= content_settings
->GetContentSetting(
163 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS
, std::string());
164 EXPECT_EQ(setting
, CONTENT_SETTING_BLOCK
);
165 setting
= content_settings
->GetContentSetting(
166 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS
, std::string());
167 EXPECT_EQ(setting
, CONTENT_SETTING_ALLOW
);
168 setting
= content_settings
->GetContentSetting(
169 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION
, std::string());
170 EXPECT_EQ(setting
, CONTENT_SETTING_ASK
);
171 setting
= content_settings
->GetContentSetting(
172 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, std::string());
173 EXPECT_EQ(setting
, CONTENT_SETTING_ASK
);
174 setting
= content_settings
->GetContentSetting(
175 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string());
176 EXPECT_EQ(setting
, CONTENT_SETTING_ASK
);
177 setting
= content_settings
->GetContentSetting(
178 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, std::string());
179 EXPECT_EQ(setting
, CONTENT_SETTING_ASK
);
181 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_
));
182 EXPECT_CALL(*mock_ui(), SetCookieInfo(_
));
183 EXPECT_CALL(*mock_ui(), SetFirstVisit(base::string16()));
185 // SetPermissionInfo() is called once initially, and then again every time
186 // OnSitePermissionChanged() is called.
187 // TODO(markusheintz): This is a temporary hack to fix issue: http://crbug.com/144203.
188 #if defined(OS_MACOSX)
189 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_
)).Times(6);
191 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_
)).Times(1);
193 EXPECT_CALL(*mock_ui(), SetSelectedTab(
194 WebsiteSettingsUI::TAB_ID_PERMISSIONS
));
196 // Execute code under tests.
197 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_POPUPS
,
198 CONTENT_SETTING_ALLOW
);
199 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_PLUGINS
,
200 CONTENT_SETTING_BLOCK
);
201 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_GEOLOCATION
,
202 CONTENT_SETTING_ALLOW
);
203 website_settings()->OnSitePermissionChanged(
204 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, CONTENT_SETTING_ALLOW
);
205 website_settings()->OnSitePermissionChanged(
206 CONTENT_SETTINGS_TYPE_MEDIASTREAM
, CONTENT_SETTING_ALLOW
);
208 // Verify that the site permissions were changed correctly.
209 setting
= content_settings
->GetContentSetting(
210 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS
, std::string());
211 EXPECT_EQ(setting
, CONTENT_SETTING_ALLOW
);
212 setting
= content_settings
->GetContentSetting(
213 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS
, std::string());
214 EXPECT_EQ(setting
, CONTENT_SETTING_BLOCK
);
215 setting
= content_settings
->GetContentSetting(
216 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION
, std::string());
217 EXPECT_EQ(setting
, CONTENT_SETTING_ALLOW
);
218 setting
= content_settings
->GetContentSetting(
219 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, std::string());
220 EXPECT_EQ(setting
, CONTENT_SETTING_ALLOW
);
221 setting
= content_settings
->GetContentSetting(
222 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string());
223 EXPECT_EQ(setting
, CONTENT_SETTING_ALLOW
);
224 setting
= content_settings
->GetContentSetting(
225 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, std::string());
226 EXPECT_EQ(setting
, CONTENT_SETTING_ALLOW
);
229 TEST_F(WebsiteSettingsTest
, OnSiteDataAccessed
) {
230 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_
));
231 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_
));
232 EXPECT_CALL(*mock_ui(), SetFirstVisit(base::string16()));
233 EXPECT_CALL(*mock_ui(), SetCookieInfo(_
)).Times(2);
234 EXPECT_CALL(*mock_ui(), SetSelectedTab(
235 WebsiteSettingsUI::TAB_ID_PERMISSIONS
));
237 website_settings()->OnSiteDataAccessed();
240 TEST_F(WebsiteSettingsTest
, HTTPConnection
) {
241 SetDefaultUIExpectations(mock_ui());
242 EXPECT_CALL(*mock_ui(), SetSelectedTab(
243 WebsiteSettingsUI::TAB_ID_PERMISSIONS
));
244 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED
,
245 website_settings()->site_connection_status());
246 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_NO_CERT
,
247 website_settings()->site_identity_status());
248 EXPECT_EQ(base::string16(), website_settings()->organization_name());
251 TEST_F(WebsiteSettingsTest
, HTTPSConnection
) {
252 ssl_
.security_style
= content::SECURITY_STYLE_AUTHENTICATED
;
253 ssl_
.cert_id
= cert_id();
254 ssl_
.cert_status
= 0;
255 ssl_
.security_bits
= 81; // No error if > 80.
257 status
= SetSSLVersion(status
, net::SSL_CONNECTION_VERSION_TLS1
);
258 status
= SetSSLCipherSuite(status
, CR_TLS_RSA_WITH_AES_256_CBC_SHA256
);
259 ssl_
.connection_status
= status
;
261 SetDefaultUIExpectations(mock_ui());
262 EXPECT_CALL(*mock_ui(), SetSelectedTab(
263 WebsiteSettingsUI::TAB_ID_PERMISSIONS
));
265 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED
,
266 website_settings()->site_connection_status());
267 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT
,
268 website_settings()->site_identity_status());
269 EXPECT_EQ(base::string16(), website_settings()->organization_name());
272 TEST_F(WebsiteSettingsTest
, HTTPSMixedContent
) {
273 ssl_
.security_style
= content::SECURITY_STYLE_AUTHENTICATED
;
274 ssl_
.cert_id
= cert_id();
275 ssl_
.cert_status
= 0;
276 ssl_
.security_bits
= 81; // No error if > 80.
277 ssl_
.content_status
= SSLStatus::DISPLAYED_INSECURE_CONTENT
;
279 status
= SetSSLVersion(status
, net::SSL_CONNECTION_VERSION_TLS1
);
280 status
= SetSSLCipherSuite(status
, CR_TLS_RSA_WITH_AES_256_CBC_SHA256
);
281 ssl_
.connection_status
= status
;
283 SetDefaultUIExpectations(mock_ui());
284 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION
));
286 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_MIXED_CONTENT
,
287 website_settings()->site_connection_status());
288 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT
,
289 website_settings()->site_identity_status());
290 EXPECT_EQ(base::string16(), website_settings()->organization_name());
293 TEST_F(WebsiteSettingsTest
, HTTPSEVCert
) {
294 scoped_refptr
<net::X509Certificate
> ev_cert
=
295 net::X509Certificate::CreateFromBytes(
296 reinterpret_cast<const char*>(google_der
),
299 EXPECT_CALL(*cert_store(), RetrieveCert(ev_cert_id
, _
)).WillRepeatedly(
300 DoAll(SetArgPointee
<1>(ev_cert
), Return(true)));
302 ssl_
.security_style
= content::SECURITY_STYLE_AUTHENTICATED
;
303 ssl_
.cert_id
= ev_cert_id
;
304 ssl_
.cert_status
= net::CERT_STATUS_IS_EV
;
305 ssl_
.security_bits
= 81; // No error if > 80.
306 ssl_
.content_status
= SSLStatus::DISPLAYED_INSECURE_CONTENT
;
308 status
= SetSSLVersion(status
, net::SSL_CONNECTION_VERSION_TLS1
);
309 status
= SetSSLCipherSuite(status
, CR_TLS_RSA_WITH_AES_256_CBC_SHA256
);
310 ssl_
.connection_status
= status
;
312 SetDefaultUIExpectations(mock_ui());
313 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION
));
315 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_MIXED_CONTENT
,
316 website_settings()->site_connection_status());
317 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT
,
318 website_settings()->site_identity_status());
319 EXPECT_EQ(base::UTF8ToUTF16("Google Inc"),
320 website_settings()->organization_name());
323 TEST_F(WebsiteSettingsTest
, HTTPSRevocationError
) {
324 ssl_
.security_style
= content::SECURITY_STYLE_AUTHENTICATED
;
325 ssl_
.cert_id
= cert_id();
326 ssl_
.cert_status
= net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION
;
327 ssl_
.security_bits
= 81; // No error if > 80.
329 status
= SetSSLVersion(status
, net::SSL_CONNECTION_VERSION_TLS1
);
330 status
= SetSSLCipherSuite(status
, CR_TLS_RSA_WITH_AES_256_CBC_SHA256
);
331 ssl_
.connection_status
= status
;
333 SetDefaultUIExpectations(mock_ui());
334 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION
));
336 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED
,
337 website_settings()->site_connection_status());
338 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN
,
339 website_settings()->site_identity_status());
340 EXPECT_EQ(base::string16(), website_settings()->organization_name());
343 TEST_F(WebsiteSettingsTest
, HTTPSConnectionError
) {
344 ssl_
.security_style
= content::SECURITY_STYLE_AUTHENTICATED
;
345 ssl_
.cert_id
= cert_id();
346 ssl_
.cert_status
= 0;
347 ssl_
.security_bits
= 1;
349 status
= SetSSLVersion(status
, net::SSL_CONNECTION_VERSION_TLS1
);
350 status
= SetSSLCipherSuite(status
, CR_TLS_RSA_WITH_AES_256_CBC_SHA256
);
351 ssl_
.connection_status
= status
;
353 SetDefaultUIExpectations(mock_ui());
354 EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION
));
356 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR
,
357 website_settings()->site_connection_status());
358 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT
,
359 website_settings()->site_identity_status());
360 EXPECT_EQ(base::string16(), website_settings()->organization_name());
363 TEST_F(WebsiteSettingsTest
, NoInfoBar
) {
364 SetDefaultUIExpectations(mock_ui());
365 EXPECT_CALL(*mock_ui(), SetSelectedTab(
366 WebsiteSettingsUI::TAB_ID_PERMISSIONS
));
367 EXPECT_EQ(0u, infobar_service()->infobar_count());
368 website_settings()->OnUIClosing();
369 EXPECT_EQ(0u, infobar_service()->infobar_count());
372 TEST_F(WebsiteSettingsTest
, ShowInfoBar
) {
373 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_
));
374 EXPECT_CALL(*mock_ui(), SetCookieInfo(_
));
375 EXPECT_CALL(*mock_ui(), SetFirstVisit(base::string16()));
377 // SetPermissionInfo() is called once initially, and then again every time
378 // OnSitePermissionChanged() is called.
379 // TODO(markusheintz): This is a temporary hack to fix issue:
380 // http://crbug.com/144203.
381 #if defined(OS_MACOSX)
382 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_
)).Times(2);
384 EXPECT_CALL(*mock_ui(), SetPermissionInfo(_
)).Times(1);
387 EXPECT_CALL(*mock_ui(), SetSelectedTab(
388 WebsiteSettingsUI::TAB_ID_PERMISSIONS
));
389 EXPECT_EQ(0u, infobar_service()->infobar_count());
390 website_settings()->OnSitePermissionChanged(
391 CONTENT_SETTINGS_TYPE_GEOLOCATION
, CONTENT_SETTING_ALLOW
);
392 website_settings()->OnUIClosing();
393 ASSERT_EQ(1u, infobar_service()->infobar_count());
395 infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));