Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ssl/chrome_expect_ct_reporter.h" | 5 #include "chrome/browser/ssl/chrome_expect_ct_reporter.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/feature_list.h" | 11 #include "base/feature_list.h" |
| 12 #include "base/json/json_reader.h" | 12 #include "base/json/json_reader.h" |
| 13 #include "base/run_loop.h" | |
| 14 #include "base/test/histogram_tester.h" | |
| 13 #include "base/values.h" | 15 #include "base/values.h" |
| 14 #include "chrome/common/chrome_features.h" | 16 #include "chrome/common/chrome_features.h" |
| 17 #include "content/public/test/test_browser_thread_bundle.h" | |
| 15 #include "net/base/test_data_directory.h" | 18 #include "net/base/test_data_directory.h" |
| 16 #include "net/ssl/signed_certificate_timestamp_and_status.h" | 19 #include "net/ssl/signed_certificate_timestamp_and_status.h" |
| 17 #include "net/test/cert_test_util.h" | 20 #include "net/test/cert_test_util.h" |
| 21 #include "net/test/url_request/url_request_failed_job.h" | |
| 18 #include "net/url_request/certificate_report_sender.h" | 22 #include "net/url_request/certificate_report_sender.h" |
| 23 #include "net/url_request/url_request_filter.h" | |
| 19 #include "net/url_request/url_request_test_util.h" | 24 #include "net/url_request/url_request_test_util.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
| 21 #include "url/gurl.h" | 26 #include "url/gurl.h" |
| 22 | 27 |
| 23 namespace { | 28 namespace { |
| 24 | 29 |
| 25 // A test CertificateReportSender that exposes the latest report URI and | 30 // A test CertificateReportSender that exposes the latest report URI and |
| 26 // serialized report to be sent. | 31 // serialized report to be sent. |
| 27 class TestCertificateReportSender : public net::CertificateReportSender { | 32 class TestCertificateReportSender : public net::CertificateReportSender { |
| 28 public: | 33 public: |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 const base::ListValue* report_invalid_scts = nullptr; | 248 const base::ListValue* report_invalid_scts = nullptr; |
| 244 ASSERT_TRUE(report_dict->GetList("invalid-scts", &report_invalid_scts)); | 249 ASSERT_TRUE(report_dict->GetList("invalid-scts", &report_invalid_scts)); |
| 245 const base::ListValue* report_valid_scts = nullptr; | 250 const base::ListValue* report_valid_scts = nullptr; |
| 246 ASSERT_TRUE(report_dict->GetList("valid-scts", &report_valid_scts)); | 251 ASSERT_TRUE(report_dict->GetList("valid-scts", &report_valid_scts)); |
| 247 | 252 |
| 248 ASSERT_NO_FATAL_FAILURE(CheckReportSCTs( | 253 ASSERT_NO_FATAL_FAILURE(CheckReportSCTs( |
| 249 ssl_info.signed_certificate_timestamps, *report_unknown_scts, | 254 ssl_info.signed_certificate_timestamps, *report_unknown_scts, |
| 250 *report_invalid_scts, *report_valid_scts)); | 255 *report_invalid_scts, *report_valid_scts)); |
| 251 } | 256 } |
| 252 | 257 |
| 258 // A test network delegate that allows the user to specify a callback to | |
| 259 // be run whenever a net::URLRequest is destroyed. | |
| 260 class TestExpectCTNetworkDelegate : public net::NetworkDelegateImpl { | |
|
meacer
2016/04/07 18:12:11
Seems like this should derive from net::NetworkDel
estark
2016/04/07 18:25:12
Hmm, I don't think so. I don't quite understand wh
meacer
2016/04/07 18:32:29
Ok never mind. Looks like NetworkDelegateImpl is j
| |
| 261 public: | |
| 262 TestExpectCTNetworkDelegate() | |
| 263 : url_request_destroyed_callback_(base::Bind(&base::DoNothing)) {} | |
| 264 | |
| 265 void set_url_request_destroyed_callback(const base::Closure& callback) { | |
| 266 url_request_destroyed_callback_ = callback; | |
| 267 } | |
| 268 | |
| 269 // net::NetworkDelegateImpl: | |
| 270 void OnURLRequestDestroyed(net::URLRequest* request) override { | |
| 271 url_request_destroyed_callback_.Run(); | |
| 272 } | |
| 273 | |
| 274 private: | |
| 275 base::Closure url_request_destroyed_callback_; | |
| 276 | |
| 277 DISALLOW_COPY_AND_ASSIGN(TestExpectCTNetworkDelegate); | |
| 278 }; | |
| 279 | |
| 280 // A test fixture that allows tests to send a report and wait until the | |
| 281 // net::URLRequest that sent the report is destroyed. | |
| 282 class ChromeExpectCTReporterWaitTest : public ::testing::Test { | |
| 283 public: | |
| 284 ChromeExpectCTReporterWaitTest() | |
| 285 : context_(true), | |
| 286 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { | |
| 287 context_.set_network_delegate(&network_delegate_); | |
| 288 context_.Init(); | |
| 289 } | |
| 290 | |
| 291 void SetUp() override { net::URLRequestFailedJob::AddUrlHandler(); } | |
| 292 | |
| 293 void TearDown() override { | |
| 294 net::URLRequestFilter::GetInstance()->ClearHandlers(); | |
| 295 } | |
| 296 | |
| 297 net::TestURLRequestContext* context() { return &context_; } | |
| 298 | |
| 299 protected: | |
| 300 void SendReport(ChromeExpectCTReporter* reporter, | |
| 301 const net::HostPortPair& host_port, | |
| 302 const GURL& report_uri, | |
| 303 const net::SSLInfo& ssl_info) { | |
| 304 base::RunLoop run_loop; | |
| 305 network_delegate_.set_url_request_destroyed_callback( | |
| 306 run_loop.QuitClosure()); | |
| 307 reporter->OnExpectCTFailed(host_port, report_uri, ssl_info); | |
| 308 run_loop.Run(); | |
| 309 } | |
| 310 | |
| 311 private: | |
| 312 TestExpectCTNetworkDelegate network_delegate_; | |
| 313 net::TestURLRequestContext context_; | |
| 314 content::TestBrowserThreadBundle thread_bundle_; | |
|
meacer
2016/04/07 18:12:11
DISALLOW_COPY_AND_ASSIGN
estark
2016/04/07 18:25:12
Done.
| |
| 315 }; | |
| 316 | |
| 253 void EnableFeature() { | 317 void EnableFeature() { |
| 254 base::FeatureList::ClearInstanceForTesting(); | 318 base::FeatureList::ClearInstanceForTesting(); |
| 255 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); | 319 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); |
| 256 feature_list->InitializeFromCommandLine(features::kExpectCTReporting.name, | 320 feature_list->InitializeFromCommandLine(features::kExpectCTReporting.name, |
| 257 ""); | 321 ""); |
| 258 base::FeatureList::SetInstance(std::move(feature_list)); | 322 base::FeatureList::SetInstance(std::move(feature_list)); |
| 259 } | 323 } |
| 260 | 324 |
| 261 } // namespace | 325 } // namespace |
| 262 | 326 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 292 reporter.report_sender_.reset(sender); | 356 reporter.report_sender_.reset(sender); |
| 293 EXPECT_TRUE(sender->latest_report_uri().is_empty()); | 357 EXPECT_TRUE(sender->latest_report_uri().is_empty()); |
| 294 EXPECT_TRUE(sender->latest_serialized_report().empty()); | 358 EXPECT_TRUE(sender->latest_serialized_report().empty()); |
| 295 | 359 |
| 296 reporter.OnExpectCTFailed(net::HostPortPair("example.test", 443), GURL(), | 360 reporter.OnExpectCTFailed(net::HostPortPair("example.test", 443), GURL(), |
| 297 net::SSLInfo()); | 361 net::SSLInfo()); |
| 298 EXPECT_TRUE(sender->latest_report_uri().is_empty()); | 362 EXPECT_TRUE(sender->latest_report_uri().is_empty()); |
| 299 EXPECT_TRUE(sender->latest_serialized_report().empty()); | 363 EXPECT_TRUE(sender->latest_serialized_report().empty()); |
| 300 } | 364 } |
| 301 | 365 |
| 366 // Test that if a report fails to send, the UMA metric is recorded. | |
| 367 TEST_F(ChromeExpectCTReporterWaitTest, SendReportFailure) { | |
| 368 EnableFeature(); | |
| 369 base::HistogramTester histograms; | |
| 370 const std::string histogram_name = "SSL.ExpectCTReportFailure"; | |
| 371 histograms.ExpectTotalCount(histogram_name, 0); | |
| 372 | |
| 373 ChromeExpectCTReporter reporter(context()); | |
| 374 | |
| 375 net::SSLInfo ssl_info; | |
| 376 ssl_info.cert = | |
| 377 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); | |
| 378 ssl_info.unverified_cert = net::ImportCertFromFile( | |
| 379 net::GetTestCertsDirectory(), "localhost_cert.pem"); | |
| 380 | |
| 381 net::HostPortPair host_port("example.test", 443); | |
| 382 GURL report_uri( | |
| 383 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED)); | |
| 384 | |
| 385 SendReport(&reporter, host_port, report_uri, ssl_info); | |
| 386 | |
| 387 histograms.ExpectTotalCount(histogram_name, 1); | |
| 388 histograms.ExpectBucketCount(histogram_name, net::ERR_CONNECTION_FAILED, 1); | |
| 389 } | |
| 390 | |
| 302 // Test that a sent report has the right format. | 391 // Test that a sent report has the right format. |
| 303 TEST(ChromeExpectCTReporterTest, SendReport) { | 392 TEST(ChromeExpectCTReporterTest, SendReport) { |
| 304 EnableFeature(); | 393 EnableFeature(); |
| 305 TestCertificateReportSender* sender = new TestCertificateReportSender(); | 394 TestCertificateReportSender* sender = new TestCertificateReportSender(); |
| 306 net::TestURLRequestContext context; | 395 net::TestURLRequestContext context; |
| 307 ChromeExpectCTReporter reporter(&context); | 396 ChromeExpectCTReporter reporter(&context); |
| 308 reporter.report_sender_.reset(sender); | 397 reporter.report_sender_.reset(sender); |
| 309 EXPECT_TRUE(sender->latest_report_uri().is_empty()); | 398 EXPECT_TRUE(sender->latest_report_uri().is_empty()); |
| 310 EXPECT_TRUE(sender->latest_serialized_report().empty()); | 399 EXPECT_TRUE(sender->latest_serialized_report().empty()); |
| 311 | 400 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 net::HostPortPair host_port("example.test", 443); | 439 net::HostPortPair host_port("example.test", 443); |
| 351 GURL report_uri("http://example-report.test"); | 440 GURL report_uri("http://example-report.test"); |
| 352 | 441 |
| 353 // Check that the report is sent and contains the correct information. | 442 // Check that the report is sent and contains the correct information. |
| 354 reporter.OnExpectCTFailed(host_port, report_uri, ssl_info); | 443 reporter.OnExpectCTFailed(host_port, report_uri, ssl_info); |
| 355 EXPECT_EQ(report_uri, sender->latest_report_uri()); | 444 EXPECT_EQ(report_uri, sender->latest_report_uri()); |
| 356 EXPECT_FALSE(sender->latest_serialized_report().empty()); | 445 EXPECT_FALSE(sender->latest_serialized_report().empty()); |
| 357 ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport( | 446 ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport( |
| 358 sender->latest_serialized_report(), host_port, ssl_info)); | 447 sender->latest_serialized_report(), host_port, ssl_info)); |
| 359 } | 448 } |
| OLD | NEW |