OLD | NEW |
| (Empty) |
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 <string> | |
8 #include <vector> | |
9 | |
10 #include "base/at_exit.h" | |
11 #include "base/bind.h" | |
12 #include "base/memory/ptr_util.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/strings/string16.h" | |
15 #include "base/strings/utf_string_conversions.h" | |
16 #include "base/test/histogram_tester.h" | |
17 #include "build/build_config.h" | |
18 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | |
19 #include "chrome/browser/infobars/infobar_service.h" | |
20 #include "chrome/browser/ui/website_settings/website_settings_ui.h" | |
21 #include "chrome/browser/usb/usb_chooser_context.h" | |
22 #include "chrome/browser/usb/usb_chooser_context_factory.h" | |
23 #include "chrome/grit/theme_resources.h" | |
24 #include "chrome/test/base/chrome_render_view_host_test_harness.h" | |
25 #include "chrome/test/base/testing_profile.h" | |
26 #include "components/content_settings/core/browser/host_content_settings_map.h" | |
27 #include "components/content_settings/core/common/content_settings.h" | |
28 #include "components/content_settings/core/common/content_settings_types.h" | |
29 #include "components/infobars/core/infobar.h" | |
30 #include "content/public/browser/ssl_status.h" | |
31 #include "device/base/mock_device_client.h" | |
32 #include "device/usb/mock_usb_device.h" | |
33 #include "device/usb/mock_usb_service.h" | |
34 #include "net/cert/cert_status_flags.h" | |
35 #include "net/cert/x509_certificate.h" | |
36 #include "net/ssl/ssl_connection_status_flags.h" | |
37 #include "net/test/cert_test_util.h" | |
38 #include "net/test/test_certificate_data.h" | |
39 #include "net/test/test_data_directory.h" | |
40 #include "ppapi/features/features.h" | |
41 #include "testing/gmock/include/gmock/gmock.h" | |
42 #include "testing/gtest/include/gtest/gtest.h" | |
43 | |
44 using content::SSLStatus; | |
45 using testing::_; | |
46 using testing::AnyNumber; | |
47 using testing::Invoke; | |
48 using testing::Return; | |
49 using testing::SetArgPointee; | |
50 | |
51 namespace { | |
52 | |
53 // SSL cipher suite like specified in RFC5246 Appendix A.5. "The Cipher Suite". | |
54 // Without the CR_ prefix, this clashes with the OS X 10.8 headers. | |
55 int CR_TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3D; | |
56 | |
57 int SetSSLVersion(int connection_status, int version) { | |
58 // Clear SSL version bits (Bits 20, 21 and 22). | |
59 connection_status &= | |
60 ~(net::SSL_CONNECTION_VERSION_MASK << net::SSL_CONNECTION_VERSION_SHIFT); | |
61 int bitmask = version << net::SSL_CONNECTION_VERSION_SHIFT; | |
62 return bitmask | connection_status; | |
63 } | |
64 | |
65 int SetSSLCipherSuite(int connection_status, int cipher_suite) { | |
66 // Clear cipher suite bits (the 16 lowest bits). | |
67 connection_status &= ~net::SSL_CONNECTION_CIPHERSUITE_MASK; | |
68 return cipher_suite | connection_status; | |
69 } | |
70 | |
71 class MockWebsiteSettingsUI : public WebsiteSettingsUI { | |
72 public: | |
73 virtual ~MockWebsiteSettingsUI() {} | |
74 MOCK_METHOD1(SetCookieInfo, void(const CookieInfoList& cookie_info_list)); | |
75 MOCK_METHOD0(SetPermissionInfoStub, void()); | |
76 MOCK_METHOD1(SetIdentityInfo, void(const IdentityInfo& identity_info)); | |
77 | |
78 void SetPermissionInfo( | |
79 const PermissionInfoList& permission_info_list, | |
80 ChosenObjectInfoList chosen_object_info_list) override { | |
81 SetPermissionInfoStub(); | |
82 if (set_permission_info_callback_) { | |
83 set_permission_info_callback_.Run(permission_info_list, | |
84 std::move(chosen_object_info_list)); | |
85 } | |
86 } | |
87 | |
88 base::Callback<void(const PermissionInfoList& permission_info_list, | |
89 ChosenObjectInfoList chosen_object_info_list)> | |
90 set_permission_info_callback_; | |
91 }; | |
92 | |
93 class WebsiteSettingsTest : public ChromeRenderViewHostTestHarness { | |
94 public: | |
95 WebsiteSettingsTest() : url_("http://www.example.com") {} | |
96 | |
97 ~WebsiteSettingsTest() override {} | |
98 | |
99 void SetUp() override { | |
100 ChromeRenderViewHostTestHarness::SetUp(); | |
101 | |
102 // Setup stub SecurityInfo. | |
103 security_info_.security_level = security_state::NONE; | |
104 | |
105 // Create the certificate. | |
106 cert_ = | |
107 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); | |
108 ASSERT_TRUE(cert_); | |
109 | |
110 TabSpecificContentSettings::CreateForWebContents(web_contents()); | |
111 InfoBarService::CreateForWebContents(web_contents()); | |
112 | |
113 // Setup mock ui. | |
114 mock_ui_.reset(new MockWebsiteSettingsUI()); | |
115 // Use this rather than gmock's ON_CALL.WillByDefault(Invoke(... because | |
116 // gmock doesn't handle move-only types well. | |
117 mock_ui_->set_permission_info_callback_ = base::Bind( | |
118 &WebsiteSettingsTest::SetPermissionInfo, base::Unretained(this)); | |
119 } | |
120 | |
121 void TearDown() override { | |
122 ASSERT_TRUE(website_settings_.get()) | |
123 << "No WebsiteSettings instance created."; | |
124 RenderViewHostTestHarness::TearDown(); | |
125 website_settings_.reset(); | |
126 } | |
127 | |
128 void SetDefaultUIExpectations(MockWebsiteSettingsUI* mock_ui) { | |
129 // During creation |WebsiteSettings| makes the following calls to the ui. | |
130 EXPECT_CALL(*mock_ui, SetPermissionInfoStub()); | |
131 EXPECT_CALL(*mock_ui, SetIdentityInfo(_)); | |
132 EXPECT_CALL(*mock_ui, SetCookieInfo(_)); | |
133 } | |
134 | |
135 void SetURL(const std::string& url) { url_ = GURL(url); } | |
136 | |
137 void SetPermissionInfo(const PermissionInfoList& permission_info_list, | |
138 ChosenObjectInfoList chosen_object_info_list) { | |
139 last_chosen_object_info_.clear(); | |
140 for (auto& chosen_object_info : chosen_object_info_list) | |
141 last_chosen_object_info_.push_back(std::move(chosen_object_info)); | |
142 } | |
143 | |
144 void ResetMockUI() { mock_ui_.reset(new MockWebsiteSettingsUI()); } | |
145 | |
146 void ClearWebsiteSettings() { website_settings_.reset(nullptr); } | |
147 | |
148 const GURL& url() const { return url_; } | |
149 scoped_refptr<net::X509Certificate> cert() { return cert_; } | |
150 MockWebsiteSettingsUI* mock_ui() { return mock_ui_.get(); } | |
151 const security_state::SecurityInfo& security_info() { | |
152 return security_info_; | |
153 } | |
154 const std::vector<std::unique_ptr<WebsiteSettingsUI::ChosenObjectInfo>>& | |
155 last_chosen_object_info() { | |
156 return last_chosen_object_info_; | |
157 } | |
158 TabSpecificContentSettings* tab_specific_content_settings() { | |
159 return TabSpecificContentSettings::FromWebContents(web_contents()); | |
160 } | |
161 InfoBarService* infobar_service() { | |
162 return InfoBarService::FromWebContents(web_contents()); | |
163 } | |
164 | |
165 WebsiteSettings* website_settings() { | |
166 if (!website_settings_.get()) { | |
167 website_settings_.reset(new WebsiteSettings( | |
168 mock_ui(), profile(), tab_specific_content_settings(), web_contents(), | |
169 url(), security_info())); | |
170 } | |
171 return website_settings_.get(); | |
172 } | |
173 | |
174 device::MockUsbService& usb_service() { | |
175 return *device_client_.usb_service(); | |
176 } | |
177 | |
178 security_state::SecurityInfo security_info_; | |
179 | |
180 private: | |
181 device::MockDeviceClient device_client_; | |
182 std::unique_ptr<WebsiteSettings> website_settings_; | |
183 std::unique_ptr<MockWebsiteSettingsUI> mock_ui_; | |
184 scoped_refptr<net::X509Certificate> cert_; | |
185 GURL url_; | |
186 std::vector<std::unique_ptr<WebsiteSettingsUI::ChosenObjectInfo>> | |
187 last_chosen_object_info_; | |
188 }; | |
189 | |
190 } // namespace | |
191 | |
192 TEST_F(WebsiteSettingsTest, OnPermissionsChanged) { | |
193 // Setup site permissions. | |
194 HostContentSettingsMap* content_settings = | |
195 HostContentSettingsMapFactory::GetForProfile(profile()); | |
196 ContentSetting setting = content_settings->GetContentSetting( | |
197 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS, std::string()); | |
198 EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); | |
199 #if BUILDFLAG(ENABLE_PLUGINS) | |
200 setting = content_settings->GetContentSetting( | |
201 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); | |
202 EXPECT_EQ(setting, CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); | |
203 #endif | |
204 setting = content_settings->GetContentSetting( | |
205 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()); | |
206 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
207 setting = content_settings->GetContentSetting( | |
208 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string()); | |
209 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
210 setting = content_settings->GetContentSetting( | |
211 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string()); | |
212 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
213 setting = content_settings->GetContentSetting( | |
214 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string()); | |
215 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
216 | |
217 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
218 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)); | |
219 | |
220 // SetPermissionInfo() is called once initially, and then again every time | |
221 // OnSitePermissionChanged() is called. | |
222 #if !BUILDFLAG(ENABLE_PLUGINS) | |
223 // SetPermissionInfo for plugins didn't get called. | |
224 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(6); | |
225 #else | |
226 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(7); | |
227 #endif | |
228 | |
229 // Execute code under tests. | |
230 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_POPUPS, | |
231 CONTENT_SETTING_ALLOW); | |
232 #if BUILDFLAG(ENABLE_PLUGINS) | |
233 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_PLUGINS, | |
234 CONTENT_SETTING_BLOCK); | |
235 #endif | |
236 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
237 CONTENT_SETTING_ALLOW); | |
238 website_settings()->OnSitePermissionChanged( | |
239 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW); | |
240 website_settings()->OnSitePermissionChanged( | |
241 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, CONTENT_SETTING_ALLOW); | |
242 website_settings()->OnSitePermissionChanged( | |
243 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, CONTENT_SETTING_ALLOW); | |
244 | |
245 // Verify that the site permissions were changed correctly. | |
246 setting = content_settings->GetContentSetting( | |
247 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS, std::string()); | |
248 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
249 #if BUILDFLAG(ENABLE_PLUGINS) | |
250 setting = content_settings->GetContentSetting( | |
251 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); | |
252 EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); | |
253 #endif | |
254 setting = content_settings->GetContentSetting( | |
255 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()); | |
256 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
257 setting = content_settings->GetContentSetting( | |
258 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string()); | |
259 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
260 setting = content_settings->GetContentSetting( | |
261 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string()); | |
262 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
263 setting = content_settings->GetContentSetting( | |
264 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string()); | |
265 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
266 } | |
267 | |
268 TEST_F(WebsiteSettingsTest, OnSiteDataAccessed) { | |
269 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()); | |
270 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
271 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)).Times(2); | |
272 | |
273 website_settings()->OnSiteDataAccessed(); | |
274 } | |
275 | |
276 TEST_F(WebsiteSettingsTest, OnChosenObjectDeleted) { | |
277 scoped_refptr<device::UsbDevice> device = | |
278 new device::MockUsbDevice(0, 0, "Google", "Gizmo", "1234567890"); | |
279 usb_service().AddDevice(device); | |
280 UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile()); | |
281 store->GrantDevicePermission(url(), url(), device->guid()); | |
282 | |
283 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
284 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)); | |
285 | |
286 // Access WebsiteSettings so that SetPermissionInfo is called once to populate | |
287 // |last_chosen_object_info_|. It will be called again by | |
288 // OnSiteChosenObjectDeleted. | |
289 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(2); | |
290 website_settings(); | |
291 | |
292 ASSERT_EQ(1u, last_chosen_object_info().size()); | |
293 const WebsiteSettingsUI::ChosenObjectInfo* info = | |
294 last_chosen_object_info()[0].get(); | |
295 website_settings()->OnSiteChosenObjectDeleted(info->ui_info, *info->object); | |
296 | |
297 EXPECT_FALSE(store->HasDevicePermission(url(), url(), device)); | |
298 EXPECT_EQ(0u, last_chosen_object_info().size()); | |
299 } | |
300 | |
301 TEST_F(WebsiteSettingsTest, Malware) { | |
302 security_info_.security_level = security_state::DANGEROUS; | |
303 security_info_.malicious_content_status = | |
304 security_state::MALICIOUS_CONTENT_STATUS_MALWARE; | |
305 SetDefaultUIExpectations(mock_ui()); | |
306 | |
307 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
308 website_settings()->site_connection_status()); | |
309 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_MALWARE, | |
310 website_settings()->site_identity_status()); | |
311 } | |
312 | |
313 TEST_F(WebsiteSettingsTest, SocialEngineering) { | |
314 security_info_.security_level = security_state::DANGEROUS; | |
315 security_info_.malicious_content_status = | |
316 security_state::MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING; | |
317 SetDefaultUIExpectations(mock_ui()); | |
318 | |
319 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
320 website_settings()->site_connection_status()); | |
321 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_SOCIAL_ENGINEERING, | |
322 website_settings()->site_identity_status()); | |
323 } | |
324 | |
325 TEST_F(WebsiteSettingsTest, UnwantedSoftware) { | |
326 security_info_.security_level = security_state::DANGEROUS; | |
327 security_info_.malicious_content_status = | |
328 security_state::MALICIOUS_CONTENT_STATUS_UNWANTED_SOFTWARE; | |
329 SetDefaultUIExpectations(mock_ui()); | |
330 | |
331 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
332 website_settings()->site_connection_status()); | |
333 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_UNWANTED_SOFTWARE, | |
334 website_settings()->site_identity_status()); | |
335 } | |
336 | |
337 TEST_F(WebsiteSettingsTest, HTTPConnection) { | |
338 SetDefaultUIExpectations(mock_ui()); | |
339 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
340 website_settings()->site_connection_status()); | |
341 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_NO_CERT, | |
342 website_settings()->site_identity_status()); | |
343 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
344 } | |
345 | |
346 TEST_F(WebsiteSettingsTest, HTTPSConnection) { | |
347 security_info_.security_level = security_state::SECURE; | |
348 security_info_.scheme_is_cryptographic = true; | |
349 security_info_.certificate = cert(); | |
350 security_info_.cert_status = 0; | |
351 security_info_.security_bits = 81; // No error if > 80. | |
352 int status = 0; | |
353 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
354 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
355 security_info_.connection_status = status; | |
356 | |
357 SetDefaultUIExpectations(mock_ui()); | |
358 | |
359 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
360 website_settings()->site_connection_status()); | |
361 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT, | |
362 website_settings()->site_identity_status()); | |
363 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
364 } | |
365 | |
366 TEST_F(WebsiteSettingsTest, InsecureContent) { | |
367 struct TestCase { | |
368 security_state::SecurityLevel security_level; | |
369 net::CertStatus cert_status; | |
370 security_state::ContentStatus mixed_content_status; | |
371 security_state::ContentStatus content_with_cert_errors_status; | |
372 WebsiteSettings::SiteConnectionStatus expected_site_connection_status; | |
373 WebsiteSettings::SiteIdentityStatus expected_site_identity_status; | |
374 int expected_connection_icon_id; | |
375 }; | |
376 | |
377 const TestCase kTestCases[] = { | |
378 // Passive mixed content. | |
379 {security_state::NONE, 0, security_state::CONTENT_STATUS_DISPLAYED, | |
380 security_state::CONTENT_STATUS_NONE, | |
381 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
382 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_WARNING_MINOR}, | |
383 // Passive mixed content with a cert error on the main resource. | |
384 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
385 security_state::CONTENT_STATUS_DISPLAYED, | |
386 security_state::CONTENT_STATUS_NONE, | |
387 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
388 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_WARNING_MINOR}, | |
389 // Active and passive mixed content. | |
390 {security_state::DANGEROUS, 0, | |
391 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
392 security_state::CONTENT_STATUS_NONE, | |
393 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
394 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
395 // Active and passive mixed content with a cert error on the main | |
396 // resource. | |
397 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
398 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
399 security_state::CONTENT_STATUS_NONE, | |
400 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
401 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_BAD}, | |
402 // Active mixed content. | |
403 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_RAN, | |
404 security_state::CONTENT_STATUS_NONE, | |
405 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
406 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
407 // Active mixed content with a cert error on the main resource. | |
408 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
409 security_state::CONTENT_STATUS_RAN, security_state::CONTENT_STATUS_NONE, | |
410 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
411 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_BAD}, | |
412 | |
413 // Passive subresources with cert errors. | |
414 {security_state::NONE, 0, security_state::CONTENT_STATUS_NONE, | |
415 security_state::CONTENT_STATUS_DISPLAYED, | |
416 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
417 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_WARNING_MINOR}, | |
418 // Passive subresources with cert errors, with a cert error on the | |
419 // main resource also. In this case, the subresources with | |
420 // certificate errors are ignored: if the main resource had a cert | |
421 // error, it's not that useful to warn about subresources with cert | |
422 // errors as well. | |
423 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
424 security_state::CONTENT_STATUS_NONE, | |
425 security_state::CONTENT_STATUS_DISPLAYED, | |
426 WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
427 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_GOOD}, | |
428 // Passive and active subresources with cert errors. | |
429 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_NONE, | |
430 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
431 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
432 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
433 // Passive and active subresources with cert errors, with a cert | |
434 // error on the main resource also. | |
435 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
436 security_state::CONTENT_STATUS_NONE, | |
437 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
438 WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
439 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_GOOD}, | |
440 // Active subresources with cert errors. | |
441 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_NONE, | |
442 security_state::CONTENT_STATUS_RAN, | |
443 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
444 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
445 // Active subresources with cert errors, with a cert error on the main | |
446 // resource also. | |
447 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
448 security_state::CONTENT_STATUS_NONE, security_state::CONTENT_STATUS_RAN, | |
449 WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
450 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_GOOD}, | |
451 | |
452 // Passive mixed content and subresources with cert errors. | |
453 {security_state::NONE, 0, security_state::CONTENT_STATUS_DISPLAYED, | |
454 security_state::CONTENT_STATUS_DISPLAYED, | |
455 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
456 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_WARNING_MINOR}, | |
457 // Passive mixed content and active subresources with cert errors. | |
458 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_DISPLAYED, | |
459 security_state::CONTENT_STATUS_RAN, | |
460 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
461 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
462 // Active mixed content and passive subresources with cert errors. | |
463 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_RAN, | |
464 security_state::CONTENT_STATUS_DISPLAYED, | |
465 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
466 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
467 // Passive mixed content, active subresources with cert errors, and a cert | |
468 // error on the main resource. | |
469 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
470 security_state::CONTENT_STATUS_DISPLAYED, | |
471 security_state::CONTENT_STATUS_RAN, | |
472 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
473 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_WARNING_MINOR}, | |
474 }; | |
475 | |
476 for (const auto& test : kTestCases) { | |
477 ResetMockUI(); | |
478 ClearWebsiteSettings(); | |
479 security_info_ = security_state::SecurityInfo(); | |
480 security_info_.security_level = test.security_level; | |
481 security_info_.scheme_is_cryptographic = true; | |
482 security_info_.certificate = cert(); | |
483 security_info_.cert_status = test.cert_status; | |
484 security_info_.security_bits = 81; // No error if > 80. | |
485 security_info_.mixed_content_status = test.mixed_content_status; | |
486 security_info_.content_with_cert_errors_status = | |
487 test.content_with_cert_errors_status; | |
488 int status = 0; | |
489 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
490 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
491 security_info_.connection_status = status; | |
492 | |
493 SetDefaultUIExpectations(mock_ui()); | |
494 | |
495 EXPECT_EQ(test.expected_site_connection_status, | |
496 website_settings()->site_connection_status()); | |
497 EXPECT_EQ(test.expected_site_identity_status, | |
498 website_settings()->site_identity_status()); | |
499 EXPECT_EQ(test.expected_connection_icon_id, | |
500 WebsiteSettingsUI::GetConnectionIconID( | |
501 website_settings()->site_connection_status())); | |
502 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
503 } | |
504 } | |
505 | |
506 TEST_F(WebsiteSettingsTest, HTTPSEVCert) { | |
507 scoped_refptr<net::X509Certificate> ev_cert = | |
508 net::X509Certificate::CreateFromBytes( | |
509 reinterpret_cast<const char*>(google_der), | |
510 sizeof(google_der)); | |
511 | |
512 security_info_.security_level = security_state::NONE; | |
513 security_info_.scheme_is_cryptographic = true; | |
514 security_info_.certificate = ev_cert; | |
515 security_info_.cert_status = net::CERT_STATUS_IS_EV; | |
516 security_info_.security_bits = 81; // No error if > 80. | |
517 security_info_.mixed_content_status = | |
518 security_state::CONTENT_STATUS_DISPLAYED; | |
519 int status = 0; | |
520 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
521 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
522 security_info_.connection_status = status; | |
523 | |
524 SetDefaultUIExpectations(mock_ui()); | |
525 | |
526 EXPECT_EQ( | |
527 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
528 website_settings()->site_connection_status()); | |
529 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT, | |
530 website_settings()->site_identity_status()); | |
531 EXPECT_EQ(base::UTF8ToUTF16("Google Inc"), | |
532 website_settings()->organization_name()); | |
533 } | |
534 | |
535 TEST_F(WebsiteSettingsTest, HTTPSRevocationError) { | |
536 security_info_.security_level = security_state::SECURE; | |
537 security_info_.scheme_is_cryptographic = true; | |
538 security_info_.certificate = cert(); | |
539 security_info_.cert_status = net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; | |
540 security_info_.security_bits = 81; // No error if > 80. | |
541 int status = 0; | |
542 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
543 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
544 security_info_.connection_status = status; | |
545 | |
546 SetDefaultUIExpectations(mock_ui()); | |
547 | |
548 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
549 website_settings()->site_connection_status()); | |
550 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN, | |
551 website_settings()->site_identity_status()); | |
552 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
553 } | |
554 | |
555 TEST_F(WebsiteSettingsTest, HTTPSConnectionError) { | |
556 security_info_.security_level = security_state::SECURE; | |
557 security_info_.scheme_is_cryptographic = true; | |
558 security_info_.certificate = cert(); | |
559 security_info_.cert_status = 0; | |
560 security_info_.security_bits = -1; | |
561 int status = 0; | |
562 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
563 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
564 security_info_.connection_status = status; | |
565 | |
566 SetDefaultUIExpectations(mock_ui()); | |
567 | |
568 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR, | |
569 website_settings()->site_connection_status()); | |
570 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT, | |
571 website_settings()->site_identity_status()); | |
572 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
573 } | |
574 | |
575 TEST_F(WebsiteSettingsTest, HTTPSPolicyCertConnection) { | |
576 security_info_.security_level = | |
577 security_state::SECURE_WITH_POLICY_INSTALLED_CERT; | |
578 security_info_.scheme_is_cryptographic = true; | |
579 security_info_.certificate = cert(); | |
580 security_info_.cert_status = 0; | |
581 security_info_.security_bits = 81; // No error if > 80. | |
582 int status = 0; | |
583 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
584 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
585 security_info_.connection_status = status; | |
586 | |
587 SetDefaultUIExpectations(mock_ui()); | |
588 | |
589 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
590 website_settings()->site_connection_status()); | |
591 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT, | |
592 website_settings()->site_identity_status()); | |
593 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
594 } | |
595 | |
596 TEST_F(WebsiteSettingsTest, HTTPSSHA1) { | |
597 security_info_.security_level = security_state::NONE; | |
598 security_info_.scheme_is_cryptographic = true; | |
599 security_info_.certificate = cert(); | |
600 security_info_.cert_status = 0; | |
601 security_info_.security_bits = 81; // No error if > 80. | |
602 int status = 0; | |
603 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
604 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
605 security_info_.connection_status = status; | |
606 security_info_.sha1_in_chain = true; | |
607 | |
608 SetDefaultUIExpectations(mock_ui()); | |
609 | |
610 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
611 website_settings()->site_connection_status()); | |
612 EXPECT_EQ( | |
613 WebsiteSettings::SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM, | |
614 website_settings()->site_identity_status()); | |
615 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
616 EXPECT_EQ(IDR_PAGEINFO_WARNING_MINOR, | |
617 WebsiteSettingsUI::GetIdentityIconID( | |
618 website_settings()->site_identity_status())); | |
619 } | |
620 | |
621 #if !defined(OS_ANDROID) | |
622 TEST_F(WebsiteSettingsTest, NoInfoBar) { | |
623 SetDefaultUIExpectations(mock_ui()); | |
624 EXPECT_EQ(0u, infobar_service()->infobar_count()); | |
625 website_settings()->OnUIClosing(); | |
626 EXPECT_EQ(0u, infobar_service()->infobar_count()); | |
627 } | |
628 | |
629 TEST_F(WebsiteSettingsTest, ShowInfoBar) { | |
630 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
631 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)); | |
632 | |
633 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(2); | |
634 | |
635 EXPECT_EQ(0u, infobar_service()->infobar_count()); | |
636 website_settings()->OnSitePermissionChanged( | |
637 CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTING_ALLOW); | |
638 website_settings()->OnUIClosing(); | |
639 ASSERT_EQ(1u, infobar_service()->infobar_count()); | |
640 | |
641 infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0)); | |
642 } | |
643 #endif | |
644 | |
645 TEST_F(WebsiteSettingsTest, AboutBlankPage) { | |
646 SetURL("about:blank"); | |
647 SetDefaultUIExpectations(mock_ui()); | |
648 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
649 website_settings()->site_connection_status()); | |
650 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_NO_CERT, | |
651 website_settings()->site_identity_status()); | |
652 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
653 } | |
654 | |
655 // On desktop, internal URLs aren't handled by WebsiteSettings class. Instead, a | |
656 // custom and simpler popup is shown, so no need to test. | |
657 #if defined(OS_ANDROID) || defined(OS_IOS) | |
658 TEST_F(WebsiteSettingsTest, InternalPage) { | |
659 SetURL("chrome://bookmarks"); | |
660 SetDefaultUIExpectations(mock_ui()); | |
661 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE, | |
662 website_settings()->site_connection_status()); | |
663 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_INTERNAL_PAGE, | |
664 website_settings()->site_identity_status()); | |
665 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
666 } | |
667 #endif | |
668 | |
669 // Tests that metrics are recorded on a WebsiteSettings for pages with | |
670 // various security levels. | |
671 TEST_F(WebsiteSettingsTest, SecurityLevelMetrics) { | |
672 struct TestCase { | |
673 const std::string url; | |
674 const security_state::SecurityLevel security_level; | |
675 const std::string histogram_name; | |
676 }; | |
677 const char kGenericHistogram[] = "WebsiteSettings.Action"; | |
678 | |
679 const TestCase kTestCases[] = { | |
680 {"https://example.test", security_state::SECURE, | |
681 "Security.PageInfo.Action.HttpsUrl.Valid"}, | |
682 {"https://example.test", security_state::EV_SECURE, | |
683 "Security.PageInfo.Action.HttpsUrl.Valid"}, | |
684 {"https://example2.test", security_state::NONE, | |
685 "Security.PageInfo.Action.HttpsUrl.Downgraded"}, | |
686 {"https://example.test", security_state::DANGEROUS, | |
687 "Security.PageInfo.Action.HttpsUrl.Dangerous"}, | |
688 {"http://example.test", security_state::HTTP_SHOW_WARNING, | |
689 "Security.PageInfo.Action.HttpUrl.Warning"}, | |
690 {"http://example.test", security_state::DANGEROUS, | |
691 "Security.PageInfo.Action.HttpUrl.Dangerous"}, | |
692 {"http://example.test", security_state::NONE, | |
693 "Security.PageInfo.Action.HttpUrl.Neutral"}, | |
694 }; | |
695 | |
696 for (const auto& test : kTestCases) { | |
697 base::HistogramTester histograms; | |
698 SetURL(test.url); | |
699 security_info_.security_level = test.security_level; | |
700 ResetMockUI(); | |
701 ClearWebsiteSettings(); | |
702 SetDefaultUIExpectations(mock_ui()); | |
703 | |
704 histograms.ExpectTotalCount(kGenericHistogram, 0); | |
705 histograms.ExpectTotalCount(test.histogram_name, 0); | |
706 | |
707 website_settings()->RecordWebsiteSettingsAction( | |
708 WebsiteSettings::WebsiteSettingsAction:: | |
709 WEBSITE_SETTINGS_OPENED); | |
710 | |
711 // RecordWebsiteSettingsAction() is called during WebsiteSettings | |
712 // creation in addition to the explicit RecordWebsiteSettingsAction() | |
713 // call, so it is called twice in total. | |
714 histograms.ExpectTotalCount(kGenericHistogram, 2); | |
715 histograms.ExpectBucketCount( | |
716 kGenericHistogram, | |
717 WebsiteSettings::WebsiteSettingsAction::WEBSITE_SETTINGS_OPENED, 2); | |
718 | |
719 histograms.ExpectTotalCount(test.histogram_name, 2); | |
720 histograms.ExpectBucketCount( | |
721 test.histogram_name, | |
722 WebsiteSettings::WebsiteSettingsAction::WEBSITE_SETTINGS_OPENED, 2); | |
723 } | |
724 } | |
OLD | NEW |