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/page_info/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/page_info/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() { return security_info_; } | |
152 const std::vector<std::unique_ptr<WebsiteSettingsUI::ChosenObjectInfo>>& | |
153 last_chosen_object_info() { | |
154 return last_chosen_object_info_; | |
155 } | |
156 TabSpecificContentSettings* tab_specific_content_settings() { | |
157 return TabSpecificContentSettings::FromWebContents(web_contents()); | |
158 } | |
159 InfoBarService* infobar_service() { | |
160 return InfoBarService::FromWebContents(web_contents()); | |
161 } | |
162 | |
163 WebsiteSettings* website_settings() { | |
164 if (!website_settings_.get()) { | |
165 website_settings_.reset(new WebsiteSettings( | |
166 mock_ui(), profile(), tab_specific_content_settings(), web_contents(), | |
167 url(), security_info())); | |
168 } | |
169 return website_settings_.get(); | |
170 } | |
171 | |
172 device::MockUsbService& usb_service() { | |
173 return *device_client_.usb_service(); | |
174 } | |
175 | |
176 security_state::SecurityInfo security_info_; | |
177 | |
178 private: | |
179 device::MockDeviceClient device_client_; | |
180 std::unique_ptr<WebsiteSettings> website_settings_; | |
181 std::unique_ptr<MockWebsiteSettingsUI> mock_ui_; | |
182 scoped_refptr<net::X509Certificate> cert_; | |
183 GURL url_; | |
184 std::vector<std::unique_ptr<WebsiteSettingsUI::ChosenObjectInfo>> | |
185 last_chosen_object_info_; | |
186 }; | |
187 | |
188 } // namespace | |
189 | |
190 TEST_F(WebsiteSettingsTest, OnPermissionsChanged) { | |
191 // Setup site permissions. | |
192 HostContentSettingsMap* content_settings = | |
193 HostContentSettingsMapFactory::GetForProfile(profile()); | |
194 ContentSetting setting = content_settings->GetContentSetting( | |
195 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS, std::string()); | |
196 EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); | |
197 #if BUILDFLAG(ENABLE_PLUGINS) | |
198 setting = content_settings->GetContentSetting( | |
199 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); | |
200 EXPECT_EQ(setting, CONTENT_SETTING_DETECT_IMPORTANT_CONTENT); | |
201 #endif | |
202 setting = content_settings->GetContentSetting( | |
203 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()); | |
204 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
205 setting = content_settings->GetContentSetting( | |
206 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string()); | |
207 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
208 setting = content_settings->GetContentSetting( | |
209 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string()); | |
210 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
211 setting = content_settings->GetContentSetting( | |
212 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string()); | |
213 EXPECT_EQ(setting, CONTENT_SETTING_ASK); | |
214 | |
215 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
216 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)); | |
217 | |
218 // SetPermissionInfo() is called once initially, and then again every time | |
219 // OnSitePermissionChanged() is called. | |
220 #if !BUILDFLAG(ENABLE_PLUGINS) | |
221 // SetPermissionInfo for plugins didn't get called. | |
222 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(6); | |
223 #else | |
224 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(7); | |
225 #endif | |
226 | |
227 // Execute code under tests. | |
228 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_POPUPS, | |
229 CONTENT_SETTING_ALLOW); | |
230 #if BUILDFLAG(ENABLE_PLUGINS) | |
231 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_PLUGINS, | |
232 CONTENT_SETTING_BLOCK); | |
233 #endif | |
234 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
235 CONTENT_SETTING_ALLOW); | |
236 website_settings()->OnSitePermissionChanged( | |
237 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW); | |
238 website_settings()->OnSitePermissionChanged( | |
239 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, CONTENT_SETTING_ALLOW); | |
240 website_settings()->OnSitePermissionChanged( | |
241 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, CONTENT_SETTING_ALLOW); | |
242 | |
243 // Verify that the site permissions were changed correctly. | |
244 setting = content_settings->GetContentSetting( | |
245 url(), url(), CONTENT_SETTINGS_TYPE_POPUPS, std::string()); | |
246 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
247 #if BUILDFLAG(ENABLE_PLUGINS) | |
248 setting = content_settings->GetContentSetting( | |
249 url(), url(), CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); | |
250 EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); | |
251 #endif | |
252 setting = content_settings->GetContentSetting( | |
253 url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()); | |
254 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
255 setting = content_settings->GetContentSetting( | |
256 url(), url(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string()); | |
257 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
258 setting = content_settings->GetContentSetting( | |
259 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string()); | |
260 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
261 setting = content_settings->GetContentSetting( | |
262 url(), url(), CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string()); | |
263 EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); | |
264 } | |
265 | |
266 TEST_F(WebsiteSettingsTest, OnSiteDataAccessed) { | |
267 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()); | |
268 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
269 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)).Times(2); | |
270 | |
271 website_settings()->OnSiteDataAccessed(); | |
272 } | |
273 | |
274 TEST_F(WebsiteSettingsTest, OnChosenObjectDeleted) { | |
275 scoped_refptr<device::UsbDevice> device = | |
276 new device::MockUsbDevice(0, 0, "Google", "Gizmo", "1234567890"); | |
277 usb_service().AddDevice(device); | |
278 UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile()); | |
279 store->GrantDevicePermission(url(), url(), device->guid()); | |
280 | |
281 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
282 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)); | |
283 | |
284 // Access WebsiteSettings so that SetPermissionInfo is called once to populate | |
285 // |last_chosen_object_info_|. It will be called again by | |
286 // OnSiteChosenObjectDeleted. | |
287 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(2); | |
288 website_settings(); | |
289 | |
290 ASSERT_EQ(1u, last_chosen_object_info().size()); | |
291 const WebsiteSettingsUI::ChosenObjectInfo* info = | |
292 last_chosen_object_info()[0].get(); | |
293 website_settings()->OnSiteChosenObjectDeleted(info->ui_info, *info->object); | |
294 | |
295 EXPECT_FALSE(store->HasDevicePermission(url(), url(), device)); | |
296 EXPECT_EQ(0u, last_chosen_object_info().size()); | |
297 } | |
298 | |
299 TEST_F(WebsiteSettingsTest, Malware) { | |
300 security_info_.security_level = security_state::DANGEROUS; | |
301 security_info_.malicious_content_status = | |
302 security_state::MALICIOUS_CONTENT_STATUS_MALWARE; | |
303 SetDefaultUIExpectations(mock_ui()); | |
304 | |
305 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
306 website_settings()->site_connection_status()); | |
307 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_MALWARE, | |
308 website_settings()->site_identity_status()); | |
309 } | |
310 | |
311 TEST_F(WebsiteSettingsTest, SocialEngineering) { | |
312 security_info_.security_level = security_state::DANGEROUS; | |
313 security_info_.malicious_content_status = | |
314 security_state::MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING; | |
315 SetDefaultUIExpectations(mock_ui()); | |
316 | |
317 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
318 website_settings()->site_connection_status()); | |
319 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_SOCIAL_ENGINEERING, | |
320 website_settings()->site_identity_status()); | |
321 } | |
322 | |
323 TEST_F(WebsiteSettingsTest, UnwantedSoftware) { | |
324 security_info_.security_level = security_state::DANGEROUS; | |
325 security_info_.malicious_content_status = | |
326 security_state::MALICIOUS_CONTENT_STATUS_UNWANTED_SOFTWARE; | |
327 SetDefaultUIExpectations(mock_ui()); | |
328 | |
329 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
330 website_settings()->site_connection_status()); | |
331 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_UNWANTED_SOFTWARE, | |
332 website_settings()->site_identity_status()); | |
333 } | |
334 | |
335 TEST_F(WebsiteSettingsTest, HTTPConnection) { | |
336 SetDefaultUIExpectations(mock_ui()); | |
337 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
338 website_settings()->site_connection_status()); | |
339 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_NO_CERT, | |
340 website_settings()->site_identity_status()); | |
341 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
342 } | |
343 | |
344 TEST_F(WebsiteSettingsTest, HTTPSConnection) { | |
345 security_info_.security_level = security_state::SECURE; | |
346 security_info_.scheme_is_cryptographic = true; | |
347 security_info_.certificate = cert(); | |
348 security_info_.cert_status = 0; | |
349 security_info_.security_bits = 81; // No error if > 80. | |
350 int status = 0; | |
351 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
352 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
353 security_info_.connection_status = status; | |
354 | |
355 SetDefaultUIExpectations(mock_ui()); | |
356 | |
357 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
358 website_settings()->site_connection_status()); | |
359 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT, | |
360 website_settings()->site_identity_status()); | |
361 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
362 } | |
363 | |
364 TEST_F(WebsiteSettingsTest, InsecureContent) { | |
365 struct TestCase { | |
366 security_state::SecurityLevel security_level; | |
367 net::CertStatus cert_status; | |
368 security_state::ContentStatus mixed_content_status; | |
369 security_state::ContentStatus content_with_cert_errors_status; | |
370 WebsiteSettings::SiteConnectionStatus expected_site_connection_status; | |
371 WebsiteSettings::SiteIdentityStatus expected_site_identity_status; | |
372 int expected_connection_icon_id; | |
373 }; | |
374 | |
375 const TestCase kTestCases[] = { | |
376 // Passive mixed content. | |
377 {security_state::NONE, 0, security_state::CONTENT_STATUS_DISPLAYED, | |
378 security_state::CONTENT_STATUS_NONE, | |
379 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
380 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_WARNING_MINOR}, | |
381 // Passive mixed content with a cert error on the main resource. | |
382 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
383 security_state::CONTENT_STATUS_DISPLAYED, | |
384 security_state::CONTENT_STATUS_NONE, | |
385 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
386 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_WARNING_MINOR}, | |
387 // Active and passive mixed content. | |
388 {security_state::DANGEROUS, 0, | |
389 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
390 security_state::CONTENT_STATUS_NONE, | |
391 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
392 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
393 // Active and passive mixed content with a cert error on the main | |
394 // resource. | |
395 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
396 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
397 security_state::CONTENT_STATUS_NONE, | |
398 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
399 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_BAD}, | |
400 // Active mixed content. | |
401 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_RAN, | |
402 security_state::CONTENT_STATUS_NONE, | |
403 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
404 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
405 // Active mixed content with a cert error on the main resource. | |
406 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
407 security_state::CONTENT_STATUS_RAN, security_state::CONTENT_STATUS_NONE, | |
408 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
409 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_BAD}, | |
410 | |
411 // Passive subresources with cert errors. | |
412 {security_state::NONE, 0, security_state::CONTENT_STATUS_NONE, | |
413 security_state::CONTENT_STATUS_DISPLAYED, | |
414 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
415 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_WARNING_MINOR}, | |
416 // Passive subresources with cert errors, with a cert error on the | |
417 // main resource also. In this case, the subresources with | |
418 // certificate errors are ignored: if the main resource had a cert | |
419 // error, it's not that useful to warn about subresources with cert | |
420 // errors as well. | |
421 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
422 security_state::CONTENT_STATUS_NONE, | |
423 security_state::CONTENT_STATUS_DISPLAYED, | |
424 WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
425 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_GOOD}, | |
426 // Passive and active subresources with cert errors. | |
427 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_NONE, | |
428 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
429 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
430 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
431 // Passive and active subresources with cert errors, with a cert | |
432 // error on the main resource also. | |
433 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
434 security_state::CONTENT_STATUS_NONE, | |
435 security_state::CONTENT_STATUS_DISPLAYED_AND_RAN, | |
436 WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
437 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_GOOD}, | |
438 // Active subresources with cert errors. | |
439 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_NONE, | |
440 security_state::CONTENT_STATUS_RAN, | |
441 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
442 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
443 // Active subresources with cert errors, with a cert error on the main | |
444 // resource also. | |
445 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
446 security_state::CONTENT_STATUS_NONE, security_state::CONTENT_STATUS_RAN, | |
447 WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
448 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_GOOD}, | |
449 | |
450 // Passive mixed content and subresources with cert errors. | |
451 {security_state::NONE, 0, security_state::CONTENT_STATUS_DISPLAYED, | |
452 security_state::CONTENT_STATUS_DISPLAYED, | |
453 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
454 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_WARNING_MINOR}, | |
455 // Passive mixed content and active subresources with cert errors. | |
456 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_DISPLAYED, | |
457 security_state::CONTENT_STATUS_RAN, | |
458 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
459 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
460 // Active mixed content and passive subresources with cert errors. | |
461 {security_state::DANGEROUS, 0, security_state::CONTENT_STATUS_RAN, | |
462 security_state::CONTENT_STATUS_DISPLAYED, | |
463 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE, | |
464 WebsiteSettings::SITE_IDENTITY_STATUS_CERT, IDR_PAGEINFO_BAD}, | |
465 // Passive mixed content, active subresources with cert errors, and a cert | |
466 // error on the main resource. | |
467 {security_state::DANGEROUS, net::CERT_STATUS_DATE_INVALID, | |
468 security_state::CONTENT_STATUS_DISPLAYED, | |
469 security_state::CONTENT_STATUS_RAN, | |
470 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
471 WebsiteSettings::SITE_IDENTITY_STATUS_ERROR, IDR_PAGEINFO_WARNING_MINOR}, | |
472 }; | |
473 | |
474 for (const auto& test : kTestCases) { | |
475 ResetMockUI(); | |
476 ClearWebsiteSettings(); | |
477 security_info_ = security_state::SecurityInfo(); | |
478 security_info_.security_level = test.security_level; | |
479 security_info_.scheme_is_cryptographic = true; | |
480 security_info_.certificate = cert(); | |
481 security_info_.cert_status = test.cert_status; | |
482 security_info_.security_bits = 81; // No error if > 80. | |
483 security_info_.mixed_content_status = test.mixed_content_status; | |
484 security_info_.content_with_cert_errors_status = | |
485 test.content_with_cert_errors_status; | |
486 int status = 0; | |
487 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
488 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
489 security_info_.connection_status = status; | |
490 | |
491 SetDefaultUIExpectations(mock_ui()); | |
492 | |
493 EXPECT_EQ(test.expected_site_connection_status, | |
494 website_settings()->site_connection_status()); | |
495 EXPECT_EQ(test.expected_site_identity_status, | |
496 website_settings()->site_identity_status()); | |
497 EXPECT_EQ(test.expected_connection_icon_id, | |
498 WebsiteSettingsUI::GetConnectionIconID( | |
499 website_settings()->site_connection_status())); | |
500 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
501 } | |
502 } | |
503 | |
504 TEST_F(WebsiteSettingsTest, HTTPSEVCert) { | |
505 scoped_refptr<net::X509Certificate> ev_cert = | |
506 net::X509Certificate::CreateFromBytes( | |
507 reinterpret_cast<const char*>(google_der), sizeof(google_der)); | |
508 ASSERT_TRUE(ev_cert); | |
509 | |
510 security_info_.security_level = security_state::NONE; | |
511 security_info_.scheme_is_cryptographic = true; | |
512 security_info_.certificate = ev_cert; | |
513 security_info_.cert_status = net::CERT_STATUS_IS_EV; | |
514 security_info_.security_bits = 81; // No error if > 80. | |
515 security_info_.mixed_content_status = | |
516 security_state::CONTENT_STATUS_DISPLAYED; | |
517 int status = 0; | |
518 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
519 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
520 security_info_.connection_status = status; | |
521 | |
522 SetDefaultUIExpectations(mock_ui()); | |
523 | |
524 EXPECT_EQ( | |
525 WebsiteSettings::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE, | |
526 website_settings()->site_connection_status()); | |
527 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT, | |
528 website_settings()->site_identity_status()); | |
529 EXPECT_EQ(base::UTF8ToUTF16("Google Inc"), | |
530 website_settings()->organization_name()); | |
531 } | |
532 | |
533 TEST_F(WebsiteSettingsTest, HTTPSRevocationError) { | |
534 security_info_.security_level = security_state::SECURE; | |
535 security_info_.scheme_is_cryptographic = true; | |
536 security_info_.certificate = cert(); | |
537 security_info_.cert_status = net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; | |
538 security_info_.security_bits = 81; // No error if > 80. | |
539 int status = 0; | |
540 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
541 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
542 security_info_.connection_status = status; | |
543 | |
544 SetDefaultUIExpectations(mock_ui()); | |
545 | |
546 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
547 website_settings()->site_connection_status()); | |
548 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN, | |
549 website_settings()->site_identity_status()); | |
550 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
551 } | |
552 | |
553 TEST_F(WebsiteSettingsTest, HTTPSConnectionError) { | |
554 security_info_.security_level = security_state::SECURE; | |
555 security_info_.scheme_is_cryptographic = true; | |
556 security_info_.certificate = cert(); | |
557 security_info_.cert_status = 0; | |
558 security_info_.security_bits = -1; | |
559 int status = 0; | |
560 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
561 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
562 security_info_.connection_status = status; | |
563 | |
564 SetDefaultUIExpectations(mock_ui()); | |
565 | |
566 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR, | |
567 website_settings()->site_connection_status()); | |
568 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_CERT, | |
569 website_settings()->site_identity_status()); | |
570 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
571 } | |
572 | |
573 TEST_F(WebsiteSettingsTest, HTTPSPolicyCertConnection) { | |
574 security_info_.security_level = | |
575 security_state::SECURE_WITH_POLICY_INSTALLED_CERT; | |
576 security_info_.scheme_is_cryptographic = true; | |
577 security_info_.certificate = cert(); | |
578 security_info_.cert_status = 0; | |
579 security_info_.security_bits = 81; // No error if > 80. | |
580 int status = 0; | |
581 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
582 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
583 security_info_.connection_status = status; | |
584 | |
585 SetDefaultUIExpectations(mock_ui()); | |
586 | |
587 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
588 website_settings()->site_connection_status()); | |
589 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT, | |
590 website_settings()->site_identity_status()); | |
591 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
592 } | |
593 | |
594 TEST_F(WebsiteSettingsTest, HTTPSSHA1) { | |
595 security_info_.security_level = security_state::NONE; | |
596 security_info_.scheme_is_cryptographic = true; | |
597 security_info_.certificate = cert(); | |
598 security_info_.cert_status = 0; | |
599 security_info_.security_bits = 81; // No error if > 80. | |
600 int status = 0; | |
601 status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1); | |
602 status = SetSSLCipherSuite(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256); | |
603 security_info_.connection_status = status; | |
604 security_info_.sha1_in_chain = true; | |
605 | |
606 SetDefaultUIExpectations(mock_ui()); | |
607 | |
608 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_ENCRYPTED, | |
609 website_settings()->site_connection_status()); | |
610 EXPECT_EQ( | |
611 WebsiteSettings::SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM, | |
612 website_settings()->site_identity_status()); | |
613 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
614 EXPECT_EQ(IDR_PAGEINFO_WARNING_MINOR, | |
615 WebsiteSettingsUI::GetIdentityIconID( | |
616 website_settings()->site_identity_status())); | |
617 } | |
618 | |
619 #if !defined(OS_ANDROID) | |
620 TEST_F(WebsiteSettingsTest, NoInfoBar) { | |
621 SetDefaultUIExpectations(mock_ui()); | |
622 EXPECT_EQ(0u, infobar_service()->infobar_count()); | |
623 website_settings()->OnUIClosing(); | |
624 EXPECT_EQ(0u, infobar_service()->infobar_count()); | |
625 } | |
626 | |
627 TEST_F(WebsiteSettingsTest, ShowInfoBar) { | |
628 EXPECT_CALL(*mock_ui(), SetIdentityInfo(_)); | |
629 EXPECT_CALL(*mock_ui(), SetCookieInfo(_)); | |
630 | |
631 EXPECT_CALL(*mock_ui(), SetPermissionInfoStub()).Times(2); | |
632 | |
633 EXPECT_EQ(0u, infobar_service()->infobar_count()); | |
634 website_settings()->OnSitePermissionChanged(CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
635 CONTENT_SETTING_ALLOW); | |
636 website_settings()->OnUIClosing(); | |
637 ASSERT_EQ(1u, infobar_service()->infobar_count()); | |
638 | |
639 infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0)); | |
640 } | |
641 #endif | |
642 | |
643 TEST_F(WebsiteSettingsTest, AboutBlankPage) { | |
644 SetURL("about:blank"); | |
645 SetDefaultUIExpectations(mock_ui()); | |
646 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_UNENCRYPTED, | |
647 website_settings()->site_connection_status()); | |
648 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_NO_CERT, | |
649 website_settings()->site_identity_status()); | |
650 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
651 } | |
652 | |
653 // On desktop, internal URLs aren't handled by WebsiteSettings class. Instead, a | |
654 // custom and simpler popup is shown, so no need to test. | |
655 #if defined(OS_ANDROID) || defined(OS_IOS) | |
656 TEST_F(WebsiteSettingsTest, InternalPage) { | |
657 SetURL("chrome://bookmarks"); | |
658 SetDefaultUIExpectations(mock_ui()); | |
659 EXPECT_EQ(WebsiteSettings::SITE_CONNECTION_STATUS_INTERNAL_PAGE, | |
660 website_settings()->site_connection_status()); | |
661 EXPECT_EQ(WebsiteSettings::SITE_IDENTITY_STATUS_INTERNAL_PAGE, | |
662 website_settings()->site_identity_status()); | |
663 EXPECT_EQ(base::string16(), website_settings()->organization_name()); | |
664 } | |
665 #endif | |
666 | |
667 // Tests that metrics are recorded on a WebsiteSettings for pages with | |
668 // various security levels. | |
669 TEST_F(WebsiteSettingsTest, SecurityLevelMetrics) { | |
670 struct TestCase { | |
671 const std::string url; | |
672 const security_state::SecurityLevel security_level; | |
673 const std::string histogram_name; | |
674 }; | |
675 const char kGenericHistogram[] = "WebsiteSettings.Action"; | |
676 | |
677 const TestCase kTestCases[] = { | |
678 {"https://example.test", security_state::SECURE, | |
679 "Security.PageInfo.Action.HttpsUrl.Valid"}, | |
680 {"https://example.test", security_state::EV_SECURE, | |
681 "Security.PageInfo.Action.HttpsUrl.Valid"}, | |
682 {"https://example2.test", security_state::NONE, | |
683 "Security.PageInfo.Action.HttpsUrl.Downgraded"}, | |
684 {"https://example.test", security_state::DANGEROUS, | |
685 "Security.PageInfo.Action.HttpsUrl.Dangerous"}, | |
686 {"http://example.test", security_state::HTTP_SHOW_WARNING, | |
687 "Security.PageInfo.Action.HttpUrl.Warning"}, | |
688 {"http://example.test", security_state::DANGEROUS, | |
689 "Security.PageInfo.Action.HttpUrl.Dangerous"}, | |
690 {"http://example.test", security_state::NONE, | |
691 "Security.PageInfo.Action.HttpUrl.Neutral"}, | |
692 }; | |
693 | |
694 for (const auto& test : kTestCases) { | |
695 base::HistogramTester histograms; | |
696 SetURL(test.url); | |
697 security_info_.security_level = test.security_level; | |
698 ResetMockUI(); | |
699 ClearWebsiteSettings(); | |
700 SetDefaultUIExpectations(mock_ui()); | |
701 | |
702 histograms.ExpectTotalCount(kGenericHistogram, 0); | |
703 histograms.ExpectTotalCount(test.histogram_name, 0); | |
704 | |
705 website_settings()->RecordWebsiteSettingsAction( | |
706 WebsiteSettings::WebsiteSettingsAction::WEBSITE_SETTINGS_OPENED); | |
707 | |
708 // RecordWebsiteSettingsAction() is called during WebsiteSettings | |
709 // creation in addition to the explicit RecordWebsiteSettingsAction() | |
710 // call, so it is called twice in total. | |
711 histograms.ExpectTotalCount(kGenericHistogram, 2); | |
712 histograms.ExpectBucketCount( | |
713 kGenericHistogram, | |
714 WebsiteSettings::WebsiteSettingsAction::WEBSITE_SETTINGS_OPENED, 2); | |
715 | |
716 histograms.ExpectTotalCount(test.histogram_name, 2); | |
717 histograms.ExpectBucketCount( | |
718 test.histogram_name, | |
719 WebsiteSettings::WebsiteSettingsAction::WEBSITE_SETTINGS_OPENED, 2); | |
720 } | |
721 } | |
OLD | NEW |