• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/ui/website_settings/website_settings.h"
6 
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_service.h"
16 #include "chrome/browser/ui/website_settings/website_settings_ui.h"
17 #include "chrome/common/content_settings.h"
18 #include "chrome/common/content_settings_types.h"
19 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "components/infobars/core/infobar.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"
30 
31 using content::SSLStatus;
32 using testing::_;
33 using testing::AnyNumber;
34 using testing::Return;
35 using testing::SetArgPointee;
36 
37 namespace {
38 
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;
42 
SetSSLVersion(int connection_status,int version)43 int SetSSLVersion(int connection_status, int version) {
44   // Clear SSL version bits (Bits 20, 21 and 22).
45   connection_status &=
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;
49 }
50 
SetSSLCipherSuite(int connection_status,int cipher_suite)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;
55 }
56 
57 class MockCertStore : public content::CertStore {
58  public:
~MockCertStore()59   virtual ~MockCertStore() {}
60   MOCK_METHOD2(StoreCert, int(net::X509Certificate*, int));
61   MOCK_METHOD2(RetrieveCert, bool(int, scoped_refptr<net::X509Certificate>*));
62 };
63 
64 class MockWebsiteSettingsUI : public WebsiteSettingsUI {
65  public:
~MockWebsiteSettingsUI()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));
73 };
74 
75 class WebsiteSettingsTest : public ChromeRenderViewHostTestHarness {
76  public:
WebsiteSettingsTest()77   WebsiteSettingsTest() : cert_id_(0), url_("http://www.example.com") {}
78 
~WebsiteSettingsTest()79   virtual ~WebsiteSettingsTest() {
80   }
81 
SetUp()82   virtual void SetUp() {
83     ChromeRenderViewHostTestHarness::SetUp();
84     // Setup stub SSLStatus.
85     ssl_.security_style = content::SECURITY_STYLE_UNAUTHENTICATED;
86 
87     // Create the certificate.
88     cert_id_ = 1;
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",
93                                      "issuer",
94                                      start_date,
95                                      expiration_date);
96 
97     TabSpecificContentSettings::CreateForWebContents(web_contents());
98     InfoBarService::CreateForWebContents(web_contents());
99 
100     // Setup the mock cert store.
101     EXPECT_CALL(cert_store_, RetrieveCert(cert_id_, _) )
102         .Times(AnyNumber())
103         .WillRepeatedly(DoAll(SetArgPointee<1>(cert_), Return(true)));
104 
105     // Setup mock ui.
106     mock_ui_.reset(new MockWebsiteSettingsUI());
107   }
108 
TearDown()109   virtual void TearDown() {
110     ASSERT_TRUE(website_settings_.get())
111         << "No WebsiteSettings instance created.";
112     RenderViewHostTestHarness::TearDown();
113     website_settings_.reset();
114   }
115 
SetDefaultUIExpectations(MockWebsiteSettingsUI * mock_ui)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()));
122   }
123 
url() const124   const GURL& url() const { return url_; }
cert_store()125   MockCertStore* cert_store() { return &cert_store_; }
cert_id()126   int cert_id() { return cert_id_; }
mock_ui()127   MockWebsiteSettingsUI* mock_ui() { return mock_ui_.get(); }
ssl()128   const SSLStatus& ssl() { return ssl_; }
tab_specific_content_settings()129   TabSpecificContentSettings* tab_specific_content_settings() {
130     return TabSpecificContentSettings::FromWebContents(web_contents());
131   }
infobar_service()132   InfoBarService* infobar_service() {
133     return InfoBarService::FromWebContents(web_contents());
134   }
135 
website_settings()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()));
141     }
142     return website_settings_.get();
143   }
144 
145   SSLStatus ssl_;
146 
147  private:
148   scoped_ptr<WebsiteSettings> website_settings_;
149   scoped_ptr<MockWebsiteSettingsUI> mock_ui_;
150   int cert_id_;
151   scoped_refptr<net::X509Certificate> cert_;
152   MockCertStore cert_store_;
153   GURL url_;
154 };
155 
156 }  // namespace
157 
TEST_F(WebsiteSettingsTest,OnPermissionsChanged)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);
180 
181   EXPECT_CALL(*mock_ui(), SetIdentityInfo(_));
182   EXPECT_CALL(*mock_ui(), SetCookieInfo(_));
183   EXPECT_CALL(*mock_ui(), SetFirstVisit(base::string16()));
184 
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);
190 #else
191   EXPECT_CALL(*mock_ui(), SetPermissionInfo(_)).Times(1);
192 #endif
193   EXPECT_CALL(*mock_ui(), SetSelectedTab(
194       WebsiteSettingsUI::TAB_ID_PERMISSIONS));
195 
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);
207 
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);
227 }
228 
TEST_F(WebsiteSettingsTest,OnSiteDataAccessed)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));
236 
237   website_settings()->OnSiteDataAccessed();
238 }
239 
TEST_F(WebsiteSettingsTest,HTTPConnection)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());
249 }
250 
TEST_F(WebsiteSettingsTest,HTTPSConnection)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.
256   int status = 0;
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;
260 
261   SetDefaultUIExpectations(mock_ui());
262   EXPECT_CALL(*mock_ui(), SetSelectedTab(
263       WebsiteSettingsUI::TAB_ID_PERMISSIONS));
264 
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());
270 }
271 
TEST_F(WebsiteSettingsTest,HTTPSMixedContent)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;
278   int status = 0;
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;
282 
283   SetDefaultUIExpectations(mock_ui());
284   EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
285 
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());
291 }
292 
TEST_F(WebsiteSettingsTest,HTTPSEVCert)293 TEST_F(WebsiteSettingsTest, HTTPSEVCert) {
294   scoped_refptr<net::X509Certificate> ev_cert =
295       net::X509Certificate::CreateFromBytes(
296           reinterpret_cast<const char*>(google_der),
297           sizeof(google_der));
298   int ev_cert_id = 1;
299   EXPECT_CALL(*cert_store(), RetrieveCert(ev_cert_id, _)).WillRepeatedly(
300       DoAll(SetArgPointee<1>(ev_cert), Return(true)));
301 
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;
307   int status = 0;
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;
311 
312   SetDefaultUIExpectations(mock_ui());
313   EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
314 
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());
321 }
322 
TEST_F(WebsiteSettingsTest,HTTPSRevocationError)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.
328   int status = 0;
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;
332 
333   SetDefaultUIExpectations(mock_ui());
334   EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
335 
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());
341 }
342 
TEST_F(WebsiteSettingsTest,HTTPSConnectionError)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;
348   int status = 0;
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;
352 
353   SetDefaultUIExpectations(mock_ui());
354   EXPECT_CALL(*mock_ui(), SetSelectedTab(WebsiteSettingsUI::TAB_ID_CONNECTION));
355 
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());
361 }
362 
TEST_F(WebsiteSettingsTest,NoInfoBar)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());
370 }
371 
TEST_F(WebsiteSettingsTest,ShowInfoBar)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()));
376 
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);
383 #else
384   EXPECT_CALL(*mock_ui(), SetPermissionInfo(_)).Times(1);
385 #endif
386 
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());
394 
395   infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));
396 }
397